diff --git a/android/app/src/main/res/drawable-hdpi/eye.png b/android/app/src/main/res/drawable-hdpi/eye.png new file mode 100644 index 00000000..1305c09e Binary files /dev/null and b/android/app/src/main/res/drawable-hdpi/eye.png differ diff --git a/android/app/src/main/res/drawable-hdpi/eye_slash.png b/android/app/src/main/res/drawable-hdpi/eye_slash.png new file mode 100644 index 00000000..61209fdd Binary files /dev/null and b/android/app/src/main/res/drawable-hdpi/eye_slash.png differ diff --git a/android/app/src/main/res/drawable-hdpi/hashtag.png b/android/app/src/main/res/drawable-hdpi/hashtag.png index 946eae13..5d4be58c 100644 Binary files a/android/app/src/main/res/drawable-hdpi/hashtag.png and b/android/app/src/main/res/drawable-hdpi/hashtag.png differ diff --git a/android/app/src/main/res/drawable-hdpi/icon_facebook.png b/android/app/src/main/res/drawable-hdpi/icon_facebook.png new file mode 100644 index 00000000..5c637c07 Binary files /dev/null and b/android/app/src/main/res/drawable-hdpi/icon_facebook.png differ diff --git a/android/app/src/main/res/drawable-hdpi/icon_github.png b/android/app/src/main/res/drawable-hdpi/icon_github.png new file mode 100644 index 00000000..32dbe331 Binary files /dev/null and b/android/app/src/main/res/drawable-hdpi/icon_github.png differ diff --git a/android/app/src/main/res/drawable-hdpi/icon_gitlab.png b/android/app/src/main/res/drawable-hdpi/icon_gitlab.png new file mode 100644 index 00000000..ce6c68bf Binary files /dev/null and b/android/app/src/main/res/drawable-hdpi/icon_gitlab.png differ diff --git a/android/app/src/main/res/drawable-hdpi/icon_google.png b/android/app/src/main/res/drawable-hdpi/icon_google.png new file mode 100644 index 00000000..c84a47c7 Binary files /dev/null and b/android/app/src/main/res/drawable-hdpi/icon_google.png differ diff --git a/android/app/src/main/res/drawable-hdpi/icon_linkedin.png b/android/app/src/main/res/drawable-hdpi/icon_linkedin.png new file mode 100644 index 00000000..93708032 Binary files /dev/null and b/android/app/src/main/res/drawable-hdpi/icon_linkedin.png differ diff --git a/android/app/src/main/res/drawable-hdpi/icon_meteor.png b/android/app/src/main/res/drawable-hdpi/icon_meteor.png new file mode 100644 index 00000000..1d793b13 Binary files /dev/null and b/android/app/src/main/res/drawable-hdpi/icon_meteor.png differ diff --git a/android/app/src/main/res/drawable-hdpi/icon_twitter.png b/android/app/src/main/res/drawable-hdpi/icon_twitter.png new file mode 100644 index 00000000..4b057edd Binary files /dev/null and b/android/app/src/main/res/drawable-hdpi/icon_twitter.png differ diff --git a/android/app/src/main/res/drawable-hdpi/key.png b/android/app/src/main/res/drawable-hdpi/key.png new file mode 100644 index 00000000..5f9471db Binary files /dev/null and b/android/app/src/main/res/drawable-hdpi/key.png differ diff --git a/android/app/src/main/res/drawable-hdpi/lock.png b/android/app/src/main/res/drawable-hdpi/lock.png index 60f2bc36..68537368 100644 Binary files a/android/app/src/main/res/drawable-hdpi/lock.png and b/android/app/src/main/res/drawable-hdpi/lock.png differ diff --git a/android/app/src/main/res/drawable-hdpi/mail.png b/android/app/src/main/res/drawable-hdpi/mail.png new file mode 100644 index 00000000..ff8b7ead Binary files /dev/null and b/android/app/src/main/res/drawable-hdpi/mail.png differ diff --git a/android/app/src/main/res/drawable-hdpi/mention.png b/android/app/src/main/res/drawable-hdpi/mention.png index 637ac5dc..1049562e 100644 Binary files a/android/app/src/main/res/drawable-hdpi/mention.png and b/android/app/src/main/res/drawable-hdpi/mention.png differ diff --git a/android/app/src/main/res/drawable-hdpi/more.png b/android/app/src/main/res/drawable-hdpi/more.png new file mode 100644 index 00000000..b92f0310 Binary files /dev/null and b/android/app/src/main/res/drawable-hdpi/more.png differ diff --git a/android/app/src/main/res/drawable-hdpi/options.png b/android/app/src/main/res/drawable-hdpi/options.png new file mode 100644 index 00000000..8e3bcc2c Binary files /dev/null and b/android/app/src/main/res/drawable-hdpi/options.png differ diff --git a/android/app/src/main/res/drawable-hdpi/subscription_hashtag.png b/android/app/src/main/res/drawable-hdpi/subscription_hashtag.png deleted file mode 100644 index 76cf0a34..00000000 Binary files a/android/app/src/main/res/drawable-hdpi/subscription_hashtag.png and /dev/null differ diff --git a/android/app/src/main/res/drawable-hdpi/subscription_lock.png b/android/app/src/main/res/drawable-hdpi/subscription_lock.png deleted file mode 100644 index 71ec7462..00000000 Binary files a/android/app/src/main/res/drawable-hdpi/subscription_lock.png and /dev/null differ diff --git a/android/app/src/main/res/drawable-hdpi/user.png b/android/app/src/main/res/drawable-hdpi/user.png new file mode 100644 index 00000000..2c5ea6ed Binary files /dev/null and b/android/app/src/main/res/drawable-hdpi/user.png differ diff --git a/android/app/src/main/res/drawable-mdpi/eye.png b/android/app/src/main/res/drawable-mdpi/eye.png new file mode 100644 index 00000000..34a12607 Binary files /dev/null and b/android/app/src/main/res/drawable-mdpi/eye.png differ diff --git a/android/app/src/main/res/drawable-mdpi/eye_slash.png b/android/app/src/main/res/drawable-mdpi/eye_slash.png new file mode 100644 index 00000000..621162a1 Binary files /dev/null and b/android/app/src/main/res/drawable-mdpi/eye_slash.png differ diff --git a/android/app/src/main/res/drawable-mdpi/hashtag.png b/android/app/src/main/res/drawable-mdpi/hashtag.png index 890f02c7..e4a79ec3 100644 Binary files a/android/app/src/main/res/drawable-mdpi/hashtag.png and b/android/app/src/main/res/drawable-mdpi/hashtag.png differ diff --git a/android/app/src/main/res/drawable-mdpi/icon_facebook.png b/android/app/src/main/res/drawable-mdpi/icon_facebook.png new file mode 100644 index 00000000..b362e2ff Binary files /dev/null and b/android/app/src/main/res/drawable-mdpi/icon_facebook.png differ diff --git a/android/app/src/main/res/drawable-mdpi/icon_github.png b/android/app/src/main/res/drawable-mdpi/icon_github.png new file mode 100644 index 00000000..af76b3fd Binary files /dev/null and b/android/app/src/main/res/drawable-mdpi/icon_github.png differ diff --git a/android/app/src/main/res/drawable-mdpi/icon_gitlab.png b/android/app/src/main/res/drawable-mdpi/icon_gitlab.png new file mode 100644 index 00000000..908f0f31 Binary files /dev/null and b/android/app/src/main/res/drawable-mdpi/icon_gitlab.png differ diff --git a/android/app/src/main/res/drawable-mdpi/icon_google.png b/android/app/src/main/res/drawable-mdpi/icon_google.png new file mode 100644 index 00000000..77677544 Binary files /dev/null and b/android/app/src/main/res/drawable-mdpi/icon_google.png differ diff --git a/android/app/src/main/res/drawable-mdpi/icon_linkedin.png b/android/app/src/main/res/drawable-mdpi/icon_linkedin.png new file mode 100644 index 00000000..29cbe97f Binary files /dev/null and b/android/app/src/main/res/drawable-mdpi/icon_linkedin.png differ diff --git a/android/app/src/main/res/drawable-mdpi/icon_meteor.png b/android/app/src/main/res/drawable-mdpi/icon_meteor.png new file mode 100644 index 00000000..5489e031 Binary files /dev/null and b/android/app/src/main/res/drawable-mdpi/icon_meteor.png differ diff --git a/android/app/src/main/res/drawable-mdpi/icon_twitter.png b/android/app/src/main/res/drawable-mdpi/icon_twitter.png new file mode 100644 index 00000000..4570f1a5 Binary files /dev/null and b/android/app/src/main/res/drawable-mdpi/icon_twitter.png differ diff --git a/android/app/src/main/res/drawable-mdpi/key.png b/android/app/src/main/res/drawable-mdpi/key.png new file mode 100644 index 00000000..b3132d59 Binary files /dev/null and b/android/app/src/main/res/drawable-mdpi/key.png differ diff --git a/android/app/src/main/res/drawable-mdpi/lock.png b/android/app/src/main/res/drawable-mdpi/lock.png index f0d911fd..a87c4495 100644 Binary files a/android/app/src/main/res/drawable-mdpi/lock.png and b/android/app/src/main/res/drawable-mdpi/lock.png differ diff --git a/android/app/src/main/res/drawable-mdpi/mail.png b/android/app/src/main/res/drawable-mdpi/mail.png new file mode 100644 index 00000000..de70ea51 Binary files /dev/null and b/android/app/src/main/res/drawable-mdpi/mail.png differ diff --git a/android/app/src/main/res/drawable-mdpi/mention.png b/android/app/src/main/res/drawable-mdpi/mention.png index 4455b43e..d02eef25 100644 Binary files a/android/app/src/main/res/drawable-mdpi/mention.png and b/android/app/src/main/res/drawable-mdpi/mention.png differ diff --git a/android/app/src/main/res/drawable-mdpi/more.png b/android/app/src/main/res/drawable-mdpi/more.png new file mode 100644 index 00000000..1423e44a Binary files /dev/null and b/android/app/src/main/res/drawable-mdpi/more.png differ diff --git a/android/app/src/main/res/drawable-mdpi/options.png b/android/app/src/main/res/drawable-mdpi/options.png new file mode 100644 index 00000000..a2bd9ecd Binary files /dev/null and b/android/app/src/main/res/drawable-mdpi/options.png differ diff --git a/android/app/src/main/res/drawable-mdpi/subscription_hashtag.png b/android/app/src/main/res/drawable-mdpi/subscription_hashtag.png deleted file mode 100644 index d3719dad..00000000 Binary files a/android/app/src/main/res/drawable-mdpi/subscription_hashtag.png and /dev/null differ diff --git a/android/app/src/main/res/drawable-mdpi/subscription_lock.png b/android/app/src/main/res/drawable-mdpi/subscription_lock.png deleted file mode 100644 index e345bfdd..00000000 Binary files a/android/app/src/main/res/drawable-mdpi/subscription_lock.png and /dev/null differ diff --git a/android/app/src/main/res/drawable-mdpi/user.png b/android/app/src/main/res/drawable-mdpi/user.png new file mode 100644 index 00000000..4ea8662c Binary files /dev/null and b/android/app/src/main/res/drawable-mdpi/user.png differ diff --git a/android/app/src/main/res/drawable-xhdpi/eye.png b/android/app/src/main/res/drawable-xhdpi/eye.png new file mode 100644 index 00000000..611c8aa0 Binary files /dev/null and b/android/app/src/main/res/drawable-xhdpi/eye.png differ diff --git a/android/app/src/main/res/drawable-xhdpi/eye_slash.png b/android/app/src/main/res/drawable-xhdpi/eye_slash.png new file mode 100644 index 00000000..6751bad0 Binary files /dev/null and b/android/app/src/main/res/drawable-xhdpi/eye_slash.png differ diff --git a/android/app/src/main/res/drawable-xhdpi/hashtag.png b/android/app/src/main/res/drawable-xhdpi/hashtag.png index 70a5b3f6..d76738e3 100644 Binary files a/android/app/src/main/res/drawable-xhdpi/hashtag.png and b/android/app/src/main/res/drawable-xhdpi/hashtag.png differ diff --git a/android/app/src/main/res/drawable-xhdpi/icon_facebook.png b/android/app/src/main/res/drawable-xhdpi/icon_facebook.png new file mode 100644 index 00000000..e9543fd0 Binary files /dev/null and b/android/app/src/main/res/drawable-xhdpi/icon_facebook.png differ diff --git a/android/app/src/main/res/drawable-xhdpi/icon_github.png b/android/app/src/main/res/drawable-xhdpi/icon_github.png new file mode 100644 index 00000000..f92f531e Binary files /dev/null and b/android/app/src/main/res/drawable-xhdpi/icon_github.png differ diff --git a/android/app/src/main/res/drawable-xhdpi/icon_gitlab.png b/android/app/src/main/res/drawable-xhdpi/icon_gitlab.png new file mode 100644 index 00000000..92a633c8 Binary files /dev/null and b/android/app/src/main/res/drawable-xhdpi/icon_gitlab.png differ diff --git a/android/app/src/main/res/drawable-xhdpi/icon_google.png b/android/app/src/main/res/drawable-xhdpi/icon_google.png new file mode 100644 index 00000000..4fb517cf Binary files /dev/null and b/android/app/src/main/res/drawable-xhdpi/icon_google.png differ diff --git a/android/app/src/main/res/drawable-xhdpi/icon_linkedin.png b/android/app/src/main/res/drawable-xhdpi/icon_linkedin.png new file mode 100644 index 00000000..e96d63de Binary files /dev/null and b/android/app/src/main/res/drawable-xhdpi/icon_linkedin.png differ diff --git a/android/app/src/main/res/drawable-xhdpi/icon_meteor.png b/android/app/src/main/res/drawable-xhdpi/icon_meteor.png new file mode 100644 index 00000000..25b8bc18 Binary files /dev/null and b/android/app/src/main/res/drawable-xhdpi/icon_meteor.png differ diff --git a/android/app/src/main/res/drawable-xhdpi/icon_twitter.png b/android/app/src/main/res/drawable-xhdpi/icon_twitter.png new file mode 100644 index 00000000..7f8cf479 Binary files /dev/null and b/android/app/src/main/res/drawable-xhdpi/icon_twitter.png differ diff --git a/android/app/src/main/res/drawable-xhdpi/key.png b/android/app/src/main/res/drawable-xhdpi/key.png new file mode 100644 index 00000000..face74d6 Binary files /dev/null and b/android/app/src/main/res/drawable-xhdpi/key.png differ diff --git a/android/app/src/main/res/drawable-xhdpi/lock.png b/android/app/src/main/res/drawable-xhdpi/lock.png index 7522c451..ba072523 100644 Binary files a/android/app/src/main/res/drawable-xhdpi/lock.png and b/android/app/src/main/res/drawable-xhdpi/lock.png differ diff --git a/android/app/src/main/res/drawable-xhdpi/mail.png b/android/app/src/main/res/drawable-xhdpi/mail.png new file mode 100644 index 00000000..2425cfa0 Binary files /dev/null and b/android/app/src/main/res/drawable-xhdpi/mail.png differ diff --git a/android/app/src/main/res/drawable-xhdpi/mention.png b/android/app/src/main/res/drawable-xhdpi/mention.png index 1f51d42f..3d64c502 100644 Binary files a/android/app/src/main/res/drawable-xhdpi/mention.png and b/android/app/src/main/res/drawable-xhdpi/mention.png differ diff --git a/android/app/src/main/res/drawable-xhdpi/more.png b/android/app/src/main/res/drawable-xhdpi/more.png new file mode 100644 index 00000000..4d8111d8 Binary files /dev/null and b/android/app/src/main/res/drawable-xhdpi/more.png differ diff --git a/android/app/src/main/res/drawable-xhdpi/options.png b/android/app/src/main/res/drawable-xhdpi/options.png new file mode 100644 index 00000000..612d02be Binary files /dev/null and b/android/app/src/main/res/drawable-xhdpi/options.png differ diff --git a/android/app/src/main/res/drawable-xhdpi/subscription_hashtag.png b/android/app/src/main/res/drawable-xhdpi/subscription_hashtag.png deleted file mode 100644 index e4a79ec3..00000000 Binary files a/android/app/src/main/res/drawable-xhdpi/subscription_hashtag.png and /dev/null differ diff --git a/android/app/src/main/res/drawable-xhdpi/subscription_lock.png b/android/app/src/main/res/drawable-xhdpi/subscription_lock.png deleted file mode 100644 index a87c4495..00000000 Binary files a/android/app/src/main/res/drawable-xhdpi/subscription_lock.png and /dev/null differ diff --git a/android/app/src/main/res/drawable-xhdpi/user.png b/android/app/src/main/res/drawable-xhdpi/user.png new file mode 100644 index 00000000..933f3b71 Binary files /dev/null and b/android/app/src/main/res/drawable-xhdpi/user.png differ diff --git a/android/app/src/main/res/drawable-xxhdpi/eye.png b/android/app/src/main/res/drawable-xxhdpi/eye.png new file mode 100644 index 00000000..e8d2a62d Binary files /dev/null and b/android/app/src/main/res/drawable-xxhdpi/eye.png differ diff --git a/android/app/src/main/res/drawable-xxhdpi/eye_slash.png b/android/app/src/main/res/drawable-xxhdpi/eye_slash.png new file mode 100644 index 00000000..ce3b4159 Binary files /dev/null and b/android/app/src/main/res/drawable-xxhdpi/eye_slash.png differ diff --git a/android/app/src/main/res/drawable-xxhdpi/hashtag.png b/android/app/src/main/res/drawable-xxhdpi/hashtag.png index 8017c826..e083190f 100644 Binary files a/android/app/src/main/res/drawable-xxhdpi/hashtag.png and b/android/app/src/main/res/drawable-xxhdpi/hashtag.png differ diff --git a/android/app/src/main/res/drawable-xxhdpi/icon_facebook.png b/android/app/src/main/res/drawable-xxhdpi/icon_facebook.png new file mode 100644 index 00000000..d6d01570 Binary files /dev/null and b/android/app/src/main/res/drawable-xxhdpi/icon_facebook.png differ diff --git a/android/app/src/main/res/drawable-xxhdpi/icon_github.png b/android/app/src/main/res/drawable-xxhdpi/icon_github.png new file mode 100644 index 00000000..de753329 Binary files /dev/null and b/android/app/src/main/res/drawable-xxhdpi/icon_github.png differ diff --git a/android/app/src/main/res/drawable-xxhdpi/icon_gitlab.png b/android/app/src/main/res/drawable-xxhdpi/icon_gitlab.png new file mode 100644 index 00000000..fb8211a7 Binary files /dev/null and b/android/app/src/main/res/drawable-xxhdpi/icon_gitlab.png differ diff --git a/android/app/src/main/res/drawable-xxhdpi/icon_google.png b/android/app/src/main/res/drawable-xxhdpi/icon_google.png new file mode 100644 index 00000000..02342b21 Binary files /dev/null and b/android/app/src/main/res/drawable-xxhdpi/icon_google.png differ diff --git a/android/app/src/main/res/drawable-xxhdpi/icon_linkedin.png b/android/app/src/main/res/drawable-xxhdpi/icon_linkedin.png new file mode 100644 index 00000000..674c9ef3 Binary files /dev/null and b/android/app/src/main/res/drawable-xxhdpi/icon_linkedin.png differ diff --git a/android/app/src/main/res/drawable-xxhdpi/icon_meteor.png b/android/app/src/main/res/drawable-xxhdpi/icon_meteor.png new file mode 100644 index 00000000..b7a0a845 Binary files /dev/null and b/android/app/src/main/res/drawable-xxhdpi/icon_meteor.png differ diff --git a/android/app/src/main/res/drawable-xxhdpi/icon_twitter.png b/android/app/src/main/res/drawable-xxhdpi/icon_twitter.png new file mode 100644 index 00000000..3faaeac1 Binary files /dev/null and b/android/app/src/main/res/drawable-xxhdpi/icon_twitter.png differ diff --git a/android/app/src/main/res/drawable-xxhdpi/key.png b/android/app/src/main/res/drawable-xxhdpi/key.png new file mode 100644 index 00000000..11206129 Binary files /dev/null and b/android/app/src/main/res/drawable-xxhdpi/key.png differ diff --git a/android/app/src/main/res/drawable-xxhdpi/lock.png b/android/app/src/main/res/drawable-xxhdpi/lock.png index 72797f88..7b310acc 100644 Binary files a/android/app/src/main/res/drawable-xxhdpi/lock.png and b/android/app/src/main/res/drawable-xxhdpi/lock.png differ diff --git a/android/app/src/main/res/drawable-xxhdpi/mail.png b/android/app/src/main/res/drawable-xxhdpi/mail.png new file mode 100644 index 00000000..3b9ad1b6 Binary files /dev/null and b/android/app/src/main/res/drawable-xxhdpi/mail.png differ diff --git a/android/app/src/main/res/drawable-xxhdpi/mention.png b/android/app/src/main/res/drawable-xxhdpi/mention.png index 29defc2c..3947ed67 100644 Binary files a/android/app/src/main/res/drawable-xxhdpi/mention.png and b/android/app/src/main/res/drawable-xxhdpi/mention.png differ diff --git a/android/app/src/main/res/drawable-xxhdpi/more.png b/android/app/src/main/res/drawable-xxhdpi/more.png new file mode 100644 index 00000000..3b7cdb0b Binary files /dev/null and b/android/app/src/main/res/drawable-xxhdpi/more.png differ diff --git a/android/app/src/main/res/drawable-xxhdpi/options.png b/android/app/src/main/res/drawable-xxhdpi/options.png new file mode 100644 index 00000000..2622837a Binary files /dev/null and b/android/app/src/main/res/drawable-xxhdpi/options.png differ diff --git a/android/app/src/main/res/drawable-xxhdpi/subscription_hashtag.png b/android/app/src/main/res/drawable-xxhdpi/subscription_hashtag.png deleted file mode 100644 index 5d4be58c..00000000 Binary files a/android/app/src/main/res/drawable-xxhdpi/subscription_hashtag.png and /dev/null differ diff --git a/android/app/src/main/res/drawable-xxhdpi/subscription_lock.png b/android/app/src/main/res/drawable-xxhdpi/subscription_lock.png deleted file mode 100644 index 68537368..00000000 Binary files a/android/app/src/main/res/drawable-xxhdpi/subscription_lock.png and /dev/null differ diff --git a/android/app/src/main/res/drawable-xxhdpi/user.png b/android/app/src/main/res/drawable-xxhdpi/user.png new file mode 100644 index 00000000..c8960e2b Binary files /dev/null and b/android/app/src/main/res/drawable-xxhdpi/user.png differ diff --git a/android/app/src/main/res/drawable-xxxhdpi/eye.png b/android/app/src/main/res/drawable-xxxhdpi/eye.png new file mode 100644 index 00000000..a30e5d3a Binary files /dev/null and b/android/app/src/main/res/drawable-xxxhdpi/eye.png differ diff --git a/android/app/src/main/res/drawable-xxxhdpi/eye_slash.png b/android/app/src/main/res/drawable-xxxhdpi/eye_slash.png new file mode 100644 index 00000000..9f7f41cc Binary files /dev/null and b/android/app/src/main/res/drawable-xxxhdpi/eye_slash.png differ diff --git a/android/app/src/main/res/drawable-xxxhdpi/hashtag.png b/android/app/src/main/res/drawable-xxxhdpi/hashtag.png index 1a88b82f..c79e0c6b 100644 Binary files a/android/app/src/main/res/drawable-xxxhdpi/hashtag.png and b/android/app/src/main/res/drawable-xxxhdpi/hashtag.png differ diff --git a/android/app/src/main/res/drawable-xxxhdpi/icon_facebook.png b/android/app/src/main/res/drawable-xxxhdpi/icon_facebook.png new file mode 100644 index 00000000..d19bdb23 Binary files /dev/null and b/android/app/src/main/res/drawable-xxxhdpi/icon_facebook.png differ diff --git a/android/app/src/main/res/drawable-xxxhdpi/icon_github.png b/android/app/src/main/res/drawable-xxxhdpi/icon_github.png new file mode 100644 index 00000000..61932967 Binary files /dev/null and b/android/app/src/main/res/drawable-xxxhdpi/icon_github.png differ diff --git a/android/app/src/main/res/drawable-xxxhdpi/icon_gitlab.png b/android/app/src/main/res/drawable-xxxhdpi/icon_gitlab.png new file mode 100644 index 00000000..01100b0f Binary files /dev/null and b/android/app/src/main/res/drawable-xxxhdpi/icon_gitlab.png differ diff --git a/android/app/src/main/res/drawable-xxxhdpi/icon_google.png b/android/app/src/main/res/drawable-xxxhdpi/icon_google.png new file mode 100644 index 00000000..7693fdfc Binary files /dev/null and b/android/app/src/main/res/drawable-xxxhdpi/icon_google.png differ diff --git a/android/app/src/main/res/drawable-xxxhdpi/icon_linkedin.png b/android/app/src/main/res/drawable-xxxhdpi/icon_linkedin.png new file mode 100644 index 00000000..677a22b7 Binary files /dev/null and b/android/app/src/main/res/drawable-xxxhdpi/icon_linkedin.png differ diff --git a/android/app/src/main/res/drawable-xxxhdpi/icon_meteor.png b/android/app/src/main/res/drawable-xxxhdpi/icon_meteor.png new file mode 100644 index 00000000..eeb52443 Binary files /dev/null and b/android/app/src/main/res/drawable-xxxhdpi/icon_meteor.png differ diff --git a/android/app/src/main/res/drawable-xxxhdpi/icon_twitter.png b/android/app/src/main/res/drawable-xxxhdpi/icon_twitter.png new file mode 100644 index 00000000..fda06f99 Binary files /dev/null and b/android/app/src/main/res/drawable-xxxhdpi/icon_twitter.png differ diff --git a/android/app/src/main/res/drawable-xxxhdpi/key.png b/android/app/src/main/res/drawable-xxxhdpi/key.png new file mode 100644 index 00000000..9879f426 Binary files /dev/null and b/android/app/src/main/res/drawable-xxxhdpi/key.png differ diff --git a/android/app/src/main/res/drawable-xxxhdpi/lock.png b/android/app/src/main/res/drawable-xxxhdpi/lock.png index e4931fe5..0673b6aa 100644 Binary files a/android/app/src/main/res/drawable-xxxhdpi/lock.png and b/android/app/src/main/res/drawable-xxxhdpi/lock.png differ diff --git a/android/app/src/main/res/drawable-xxxhdpi/mail.png b/android/app/src/main/res/drawable-xxxhdpi/mail.png new file mode 100644 index 00000000..780afd4d Binary files /dev/null and b/android/app/src/main/res/drawable-xxxhdpi/mail.png differ diff --git a/android/app/src/main/res/drawable-xxxhdpi/mention.png b/android/app/src/main/res/drawable-xxxhdpi/mention.png index 14b2374d..5ef79b4b 100644 Binary files a/android/app/src/main/res/drawable-xxxhdpi/mention.png and b/android/app/src/main/res/drawable-xxxhdpi/mention.png differ diff --git a/android/app/src/main/res/drawable-xxxhdpi/more.png b/android/app/src/main/res/drawable-xxxhdpi/more.png new file mode 100644 index 00000000..7c8ab1ce Binary files /dev/null and b/android/app/src/main/res/drawable-xxxhdpi/more.png differ diff --git a/android/app/src/main/res/drawable-xxxhdpi/options.png b/android/app/src/main/res/drawable-xxxhdpi/options.png new file mode 100644 index 00000000..f9a4f021 Binary files /dev/null and b/android/app/src/main/res/drawable-xxxhdpi/options.png differ diff --git a/android/app/src/main/res/drawable-xxxhdpi/subscription_hashtag.png b/android/app/src/main/res/drawable-xxxhdpi/subscription_hashtag.png deleted file mode 100644 index d76738e3..00000000 Binary files a/android/app/src/main/res/drawable-xxxhdpi/subscription_hashtag.png and /dev/null differ diff --git a/android/app/src/main/res/drawable-xxxhdpi/subscription_lock.png b/android/app/src/main/res/drawable-xxxhdpi/subscription_lock.png deleted file mode 100644 index ba072523..00000000 Binary files a/android/app/src/main/res/drawable-xxxhdpi/subscription_lock.png and /dev/null differ diff --git a/android/app/src/main/res/drawable-xxxhdpi/user.png b/android/app/src/main/res/drawable-xxxhdpi/user.png new file mode 100644 index 00000000..b4374ec0 Binary files /dev/null and b/android/app/src/main/res/drawable-xxxhdpi/user.png differ diff --git a/app/actions/actionsTypes.js b/app/actions/actionsTypes.js index e7b82839..7c191903 100644 --- a/app/actions/actionsTypes.js +++ b/app/actions/actionsTypes.js @@ -16,22 +16,14 @@ export const LOGIN = createRequestTypes('LOGIN', [ 'SUBMIT', 'REGISTER_SUBMIT', 'REGISTER_REQUEST', - 'REGISTER_SUCCESS', - 'REGISTER_INCOMPLETE', 'SET_USERNAME_SUBMIT', 'SET_USERNAME_REQUEST', 'SET_USERNAME_SUCCESS', - 'OPEN', - 'CLOSE', 'SET_SERVICES', - 'REMOVE_SERVICES', 'SET_PREFERENCE', 'SET_SORT_PREFERENCE' ]); -export const FORGOT_PASSWORD = createRequestTypes('FORGOT_PASSWORD', [ - ...defaultTypes, - 'INIT' -]); +export const FORGOT_PASSWORD = createRequestTypes('FORGOT_PASSWORD'); export const USER = createRequestTypes('USER', ['SET']); export const ROOMS = createRequestTypes('ROOMS', [ ...defaultTypes, diff --git a/app/actions/login.js b/app/actions/login.js index 529039ce..cc5c1715 100644 --- a/app/actions/login.js +++ b/app/actions/login.js @@ -19,23 +19,13 @@ export function registerSubmit(credentials) { credentials }; } + export function registerRequest(credentials) { return { type: types.LOGIN.REGISTER_REQUEST, credentials }; } -export function registerSuccess(credentials) { - return { - type: types.LOGIN.REGISTER_SUCCESS, - credentials - }; -} -export function registerIncomplete() { - return { - type: types.LOGIN.REGISTER_INCOMPLETE - }; -} export function setUsernameSubmit(credentials) { return { @@ -127,18 +117,6 @@ export function setUser(action) { }; } -export function open() { - return { - type: types.LOGIN.OPEN - }; -} - -export function close() { - return { - type: types.LOGIN.CLOSE - }; -} - export function setLoginServices(data) { return { type: types.LOGIN.SET_SERVICES, @@ -146,12 +124,6 @@ export function setLoginServices(data) { }; } -export function removeLoginServices() { - return { - type: types.LOGIN.REMOVE_SERVICES - }; -} - export function setPreference(preference) { return { type: types.LOGIN.SET_PREFERENCE, diff --git a/app/constants/colors.js b/app/constants/colors.js index e7545cca..be30581e 100644 --- a/app/constants/colors.js +++ b/app/constants/colors.js @@ -1,5 +1,5 @@ export const COLOR_DANGER = '#f5455c'; -export const COLOR_BUTTON_PRIMARY = '#2D6AEA'; +export const COLOR_BUTTON_PRIMARY = '#1d74f5'; export const COLOR_TEXT = '#292E35'; export const COLOR_SEPARATOR = '#CBCED1'; export const STATUS_COLORS = { diff --git a/app/constants/headerOptions.js b/app/constants/headerOptions.js new file mode 100644 index 00000000..a02384fc --- /dev/null +++ b/app/constants/headerOptions.js @@ -0,0 +1,60 @@ +import { Platform } from 'react-native'; + +export const DARK_HEADER = { + statusBar: { + backgroundColor: '#2F343D', + style: 'light' + }, + topBar: { + backButton: { + color: '#fff' + }, + background: { + color: '#2F343D' + }, + title: { + color: '#FFF' + }, + leftButtonStyle: { + color: '#FFF' + }, + rightButtonStyle: { + color: '#FFF' + } + } +}; + +export const LIGHT_HEADER = { + statusBar: { + backgroundColor: '#FFF', + style: 'dark' + }, + topBar: { + backButton: { + color: '#1d74f5' + }, + background: { + color: undefined + }, + title: { + color: '#0C0D0F' + }, + leftButtonStyle: { + color: '#1d74f5' + }, + rightButtonStyle: { + color: '#1d74f5' + } + } +}; + +export const DEFAULT_HEADER = { + ...Platform.select({ + ios: { + ...LIGHT_HEADER + }, + android: { + ...DARK_HEADER + } + }) +}; diff --git a/app/constants/settings.js b/app/constants/settings.js index ec991626..12277bf5 100644 --- a/app/constants/settings.js +++ b/app/constants/settings.js @@ -8,33 +8,9 @@ export default { Accounts_NamePlaceholder: { type: 'valueAsString' }, - Accounts_OAuth_Facebook: { - type: 'valueAsBoolean' - }, - Accounts_OAuth_Github: { - type: 'valueAsBoolean' - }, - Accounts_OAuth_Gitlab: { - type: 'valueAsBoolean' - }, - Accounts_OAuth_Google: { - type: 'valueAsBoolean' - }, - Accounts_OAuth_Linkedin: { - type: 'valueAsBoolean' - }, - Accounts_OAuth_Meteor: { - type: 'valueAsBoolean' - }, - Accounts_OAuth_Twitter: { - type: 'valueAsBoolean' - }, Accounts_PasswordPlaceholder: { type: 'valueAsString' }, - Accounts_RepeatPasswordPlaceholder: { - type: 'valueAsString' - }, CROWD_Enable: { type: 'valueAsBoolean' }, @@ -84,4 +60,4 @@ export default { type: 'valueAsBoolean' } }; -export const settingsUpdatedAt = new Date('2018-09-10'); +export const settingsUpdatedAt = new Date('2018-11-14'); diff --git a/app/containers/Button/index.js b/app/containers/Button/index.js index f1f3ade3..b632abc5 100644 --- a/app/containers/Button/index.js +++ b/app/containers/Button/index.js @@ -1,32 +1,30 @@ import React from 'react'; import PropTypes from 'prop-types'; -import { - StyleSheet, View, Text, Platform, ActivityIndicator -} from 'react-native'; +import { StyleSheet, Text, ActivityIndicator } from 'react-native'; +import { RectButton } from 'react-native-gesture-handler'; -import { COLOR_BUTTON_PRIMARY, COLOR_TEXT } from '../../constants/colors'; -import Touch from '../../utils/touch'; -import { scale, moderateScale, verticalScale } from '../../utils/scaling'; +import { COLOR_BUTTON_PRIMARY } from '../../constants/colors'; +import sharedStyles from '../../views/Styles'; const colors = { background_primary: COLOR_BUTTON_PRIMARY, background_secondary: 'white', text_color_primary: 'white', - text_color_secondary: COLOR_TEXT + text_color_secondary: COLOR_BUTTON_PRIMARY }; /* eslint-disable react-native/no-unused-styles */ const styles = StyleSheet.create({ container: { - paddingHorizontal: scale(15), + paddingHorizontal: 15, justifyContent: 'center', - height: scale(48) + height: 48, + borderRadius: 2, + marginBottom: 10 }, text: { - fontSize: moderateScale(18), - height: verticalScale(20), - lineHeight: verticalScale(20), + fontSize: 18, textAlign: 'center', fontWeight: '500' }, @@ -36,30 +34,25 @@ const styles = StyleSheet.create({ background_secondary: { backgroundColor: colors.background_secondary }, - text_color_primary: { + text_primary: { + ...sharedStyles.textMedium, color: colors.text_color_primary }, - text_color_secondary: { + text_secondary: { + ...sharedStyles.textBold, color: colors.text_color_secondary }, - margin: { - marginBottom: verticalScale(10) - }, disabled: { - opacity: 0.5 - }, - border: { - borderRadius: scale(2) + backgroundColor: '#e1e5e8' } }); export default class Button extends React.PureComponent { static propTypes = { - title: PropTypes.string, + title: PropTypes.oneOfType([PropTypes.string, PropTypes.element]), type: PropTypes.string, onPress: PropTypes.func, disabled: PropTypes.bool, - margin: PropTypes.any, backgroundColor: PropTypes.string, loading: PropTypes.bool } @@ -74,32 +67,26 @@ export default class Button extends React.PureComponent { render() { const { - title, type, onPress, disabled, margin, backgroundColor, loading, ...otherProps + title, type, onPress, disabled, backgroundColor, loading, ...otherProps } = this.props; return ( - - - { - loading - ? - : {title} - } - - + { + loading + ? + : {title} + } + ); } } diff --git a/app/containers/Sidebar.js b/app/containers/Sidebar.js index bec5be29..975606dc 100644 --- a/app/containers/Sidebar.js +++ b/app/containers/Sidebar.js @@ -85,7 +85,7 @@ const styles = StyleSheet.create({ const keyExtractor = item => item.id; @connect(state => ({ - server: state.server.server, + Site_Name: state.settings.Site_Name, user: { id: state.login.user && state.login.user.id, language: state.login.user && state.login.user.language, @@ -101,7 +101,7 @@ export default class Sidebar extends Component { static propTypes = { baseUrl: PropTypes.string, componentId: PropTypes.string, - server: PropTypes.string.isRequired, + Site_Name: PropTypes.string.isRequired, user: PropTypes.object, logout: PropTypes.func.isRequired, appStart: PropTypes.func @@ -289,7 +289,7 @@ export default class Sidebar extends Component { render() { const { showStatus } = this.state; - const { user, server, baseUrl } = this.props; + const { user, Site_Name, baseUrl } = this.props; if (!user) { return null; @@ -315,7 +315,7 @@ export default class Sidebar extends Component { {user.username} - {server} + {Site_Name} - - iconLeft = (name) => { - const { testID } = this.props; - return this.icon({ - name, - onPress: null, - style: { left: 0 }, - testID: testID ? `${ testID }-icon-left` : null - }); + get iconLeft() { + const { testID, iconLeft } = this.props; + return ( + + ); } - iconPassword = (name) => { + get iconPassword() { + const { showPassword } = this.state; const { testID } = this.props; - return this.icon({ - name, - onPress: () => this.tooglePassword(), - style: { right: 0 }, - testID: testID ? `${ testID }-icon-right` : null - }); + return ( + + + + ); } tooglePassword = () => { - const { showPassword } = this.state; - this.setState({ showPassword: !showPassword }); + this.setState(prevState => ({ showPassword: !prevState.showPassword })); } render() { + const { showPassword } = this.state; const { label, error, secureTextEntry, containerStyle, inputRef, iconLeft, inputStyle, testID, placeholder, ...inputProps } = this.props; - const { showPassword } = this.state; return ( - {label ? {label} : null } + {label ? {label} : null} - {iconLeft ? this.iconLeft(iconLeft) : null} - {secureTextEntry ? this.iconPassword(showPassword ? 'eye-off' : 'eye') : null} + {iconLeft ? this.iconLeft : null} + {secureTextEntry ? this.iconPassword : null} {error.error ? {error.reason} : null} diff --git a/app/i18n/locales/en.js b/app/i18n/locales/en.js index 9f67b428..74563eed 100644 --- a/app/i18n/locales/en.js +++ b/app/i18n/locales/en.js @@ -121,14 +121,16 @@ export default { Choose_from_library: 'Choose from library', Code: 'Code', Collaborative: 'Collaborative', + Confirm: 'Confirm', Connect: 'Connect', Connect_to_a_server: 'Connect to a server', Connected: 'Connected', Connecting: 'Connecting...', + Continue_with: 'Continue with', Copied_to_clipboard: 'Copied to clipboard!', Copy_Message: 'Copy Message', Copy_Permalink: 'Copy Permalink', - Create_account: 'Create account', + Create_account: 'Create an account', Create_Channel: 'Create Channel', Create_a_new_workspace: 'Create a new workspace', Create: 'Create', @@ -140,12 +142,14 @@ export default { Description: 'Description', Disable_notifications: 'Disable notifications', Direct_Messages: 'Direct Messages', + Dont_Have_An_Account: 'Don\'t have an account?', Do_you_really_want_to_key_this_room_question_mark: 'Do you really want to {{key}} this room?', edit: 'edit', erasing_room: 'erasing room', Edit: 'Edit', Email_or_password_field_is_empty: 'Email or password field is empty', Email: 'Email', + email: 'e-mail', Enable_notifications: 'Enable notifications', Everyone_can_access_this_channel: 'Everyone can access this channel', Error_uploading: 'Error uploading', @@ -161,7 +165,6 @@ export default { Group_by_type: 'Group by type', Has_joined_the_channel: 'Has joined the channel', Has_left_the_channel: 'Has left the channel', - I_have_an_account: 'I have an account', Invisible: 'Invisible', Invite: 'Invite', is_a_valid_RocketChat_instance: 'is a valid Rocket.Chat instance', @@ -175,8 +178,11 @@ export default { Leave_channel: 'Leave channel', leaving_room: 'leaving room', leave: 'leave', + Legal: 'Legal', Livechat: 'Livechat', Login: 'Login', + Login_error: 'Your credentials were rejected! Please try again.', + Login_with: 'Login with', Logout: 'Logout', Members: 'Members', Mentioned_Messages: 'Mentioned Messages', @@ -197,7 +203,6 @@ export default { N_users: '{{n}} users', name: 'name', Name: 'Name', - New_in_RocketChat_question_mark: 'New in Rocket.Chat?', New_Message: 'New Message', New_Password: 'New Password', New_Server: 'New Server', @@ -222,7 +227,6 @@ export default { Only_authorized_users_can_write_new_messages: 'Only authorized users can write new messages', Open_emoji_selector: 'Open emoji selector', Open_Source_Communication: 'Open Source Communication', - Or_continue_using_social_accounts: 'Or continue using social accounts', Password: 'Password', Permalink_copied_to_clipboard: 'Permalink copied to clipboard!', Pin: 'Pin', @@ -277,6 +281,7 @@ export default { Send_message: 'Send message', Server: 'Server', Servers: 'Servers', + Set_username_subtitle: 'The username is used to allow others to mention you in messages', Settings: 'Settings', Settings_succesfully_changed: 'Settings succesfully changed!', Share_Message: 'Share Message', @@ -308,6 +313,7 @@ export default { topic: 'topic', Topic: 'Topic', Try_again: 'Try again', + Two_Factor_Authentication: 'Two-factor Authentication', Type_the_channel_name_here: 'Type the channel name here', unarchive: 'unarchive', UNARCHIVE: 'UNARCHIVE', @@ -330,13 +336,13 @@ export default { User_was_set_role_by_: '{{user}} was set {{role}} by {{userBy}}', Username_is_empty: 'Username is empty', Username: 'Username', + Username_or_email: 'Username or email', Validating: 'Validating', Video_call: 'Video call', Voice_call: 'Voice call', Welcome: 'Welcome', - Welcome_title_pt_1: 'Prepare to take off with', - Welcome_title_pt_2: 'the ultimate chat platform', Welcome_to_RocketChat: 'Welcome to Rocket.Chat', + Whats_your_2fa: 'What\'s your 2FA code?', Yes_action_it: 'Yes, {{action}} it!', Yesterday: 'Yesterday', You_are_in_preview_mode: 'You are in preview mode', diff --git a/app/i18n/locales/pt-BR.js b/app/i18n/locales/pt-BR.js index bce2d48e..3232282b 100644 --- a/app/i18n/locales/pt-BR.js +++ b/app/i18n/locales/pt-BR.js @@ -128,10 +128,12 @@ export default { Choose_from_library: 'Escolha da biblioteca', Code: 'Código', Collaborative: 'Colaborativo', + Confirm: 'Confirmar', Connect: 'Conectar', Connect_to_a_server: 'Conectar a um servidor', Connected: 'Conectado', Connecting: 'Conectando...', + Continue_with: 'Entrar com', Copied_to_clipboard: 'Copiado para a área de transferência!', Copy_Message: 'Copiar Mensagem', Copy_Permalink: 'Copiar Link-Permanente', @@ -147,12 +149,14 @@ export default { Description: 'Descrição', Disable_notifications: 'Desabilitar notificações', Direct_Messages: 'Mensagens Diretas', + Dont_Have_An_Account: 'Não tem uma conta?', Do_you_really_want_to_key_this_room_question_mark: 'Você quer realmente {{key}} esta sala?', edit: 'editar', erasing_room: 'apagando sala', Edit: 'Editar', Email_or_password_field_is_empty: 'Email ou senha estão vazios', Email: 'Email', + email: 'e-mail', Enable_notifications: 'Habilitar notificações', Everyone_can_access_this_channel: 'Todos podem acessar este canal', Error_uploading: 'Erro subindo', @@ -168,7 +172,6 @@ export default { Group_by_type: 'Grupos por tipo', Has_joined_the_channel: 'Entrou no canal', Has_left_the_channel: 'Saiu da conversa', - I_have_an_account: 'Eu tenho uma conta', Invisible: 'Invisível', Invite: 'Convidar', is_typing: 'está digitando', @@ -180,8 +183,11 @@ export default { Leave_channel: 'Sair do canal', leaving_room: 'saindo do canal', leave: 'sair', + Legal: 'Legal', Livechat: 'Livechat', Login: 'Entrar', + Login_error: 'Suas credenciais foram rejeitadas. Tente novamente por favor!', + Login_with: 'Login with', Logout: 'Sair', Members: 'Membros', Mentioned_Messages: 'Mensagens mencionadas', @@ -224,7 +230,6 @@ export default { Only_authorized_users_can_write_new_messages: 'Somente usuários autorizados podem escrever novas mensagens', Open_emoji_selector: 'Abrir seletor de emoji', Open_Source_Communication: 'Comunicação Open Source', - Or_continue_using_social_accounts: 'Ou continue usando redes sociais', Password: 'Senha', Permalink_copied_to_clipboard: 'Link-permanente copiado para a área de transferência!', Pin: 'Fixar', @@ -278,6 +283,7 @@ export default { Send_audio_message: 'Enviar mensagem de áudio', Send_message: 'Enviar mensagem', Server: 'Servidor', + Set_username_subtitle: 'O usuário é utilizado para permitir que você seja mencionado em mensagens', Settings: 'Configurações', Settings_succesfully_changed: 'Configurações salvas com sucesso!', Share_Message: 'Compartilhar Mensagem', @@ -306,6 +312,7 @@ export default { topic: 'tópico', Topic: 'Tópico', Try_again: 'Tentar novamente', + Two_Factor_Authentication: 'Autenticação de dois fatores', Type_the_channel_name_here: 'Digite o nome do canal', unarchive: 'desarquivar', UNARCHIVE: 'DESARQUIVAR', @@ -328,12 +335,12 @@ export default { User_was_set_role_by_: '{{user}} foi definido como {{role}} por {{userBy}}', Username_is_empty: 'Usuário está vazio', Username: 'Usuário', + Username_or_email: 'Usuário ou email', Video_call: 'Chamada de vídeo', Voice_call: 'Chamada de voz', Welcome: 'Bem vindo', - Welcome_title_pt_1: 'Prepare-se para decolar com', - Welcome_title_pt_2: 'a melhor plataforma de chat', Welcome_to_RocketChat: 'Bem vindo ao Rocket.Chat', + Whats_your_2fa: 'Qual seu código de autenticação?', Yes_action_it: 'Sim, {{action}}!', Yesterday: 'Ontem', You_are_in_preview_mode: 'Está é uma prévia do canal', diff --git a/app/i18n/locales/ru.js b/app/i18n/locales/ru.js index b7bf873a..7fb8a0cc 100644 --- a/app/i18n/locales/ru.js +++ b/app/i18n/locales/ru.js @@ -200,7 +200,6 @@ export default { Online: 'Онлайн', Only_authorized_users_can_write_new_messages: 'Только авторизованные пользователи могут писать новые сообщения', Open_emoji_selector: 'Открыть селектор emoji', - Or_continue_using_social_accounts: 'Или продолжить, используя социальные учетные записи', Password: 'Пароль', Permalink_copied_to_clipboard: 'Постоянная ссылка скопирована в буфер обмена!', Pin: 'Прикрепить сообщение', @@ -305,8 +304,6 @@ export default { Video_call: 'Видеозвонок', Voice_call: 'Голосовой вызов', Welcome: 'Добро пожаловать', - Welcome_title_pt_1: 'Приготовьтесь к взлету с', - Welcome_title_pt_2: 'передовой чат-платформой', Yes_action_it: 'Да, {{action}} это!', Yesterday: 'Вчера', You_are_in_preview_mode: 'Вы находитесь в режиме предварительного просмотра', diff --git a/app/i18n/locales/zh-CN.js b/app/i18n/locales/zh-CN.js index 355435e3..a5352d3c 100644 --- a/app/i18n/locales/zh-CN.js +++ b/app/i18n/locales/zh-CN.js @@ -222,7 +222,6 @@ export default { Only_authorized_users_can_write_new_messages: '只有经过授权的用户才能写新消息', Open_emoji_selector: '打开emoji选择器', Open_Source_Communication: '开源沟通', - Or_continue_using_social_accounts: '或者继续使用社交账号', Password: '密码', Permalink_copied_to_clipboard: '永久链接已复制到剪贴板!', Pin: '订住', @@ -333,8 +332,6 @@ export default { Video_call: '视频电话', Voice_call: '语音电话', Welcome: '欢迎', - Welcome_title_pt_1: '准备起飞', - Welcome_title_pt_2: '终极聊天平台', Welcome_to_RocketChat: '欢迎来到 Rocket.Chat', Yes_action_it: '是的,{{action}}它!', Yesterday: '昨天', diff --git a/app/index.js b/app/index.js index 4acf28f3..c6cb8f6f 100644 --- a/app/index.js +++ b/app/index.js @@ -1,6 +1,8 @@ import { Component } from 'react'; -import { Linking, Platform, Dimensions } from 'react-native'; +import { Linking, Platform } from 'react-native'; import { Navigation } from 'react-native-navigation'; +import { Provider } from 'react-redux'; +import { gestureHandlerRootHOC } from 'react-native-gesture-handler'; import store from './lib/createStore'; import { appInit } from './actions'; @@ -10,8 +12,6 @@ import { deepLinkingOpen } from './actions/deepLinking'; import parseQuery from './lib/methods/helpers/parseQuery'; import { initializePushNotifications } from './push'; -const isAndroid = () => Platform.OS === 'android'; - const startLogged = () => { Navigation.setRoot({ root: { @@ -57,6 +57,30 @@ const startNotLogged = () => { }); }; +let SetUsernameView = null; +const startSetUsername = () => { + if (SetUsernameView == null) { + SetUsernameView = require('./views/SetUsernameView').default; + Navigation.registerComponentWithRedux('SetUsernameView', () => gestureHandlerRootHOC(SetUsernameView), Provider, store); + } + Navigation.setRoot({ + root: { + stack: { + children: [{ + component: { + name: 'SetUsernameView' + } + }], + options: { + layout: { + orientation: ['portrait'] + } + } + } + } + }); +}; + const handleOpenURL = ({ url }) => { if (url) { url = url.replace(/rocketchat:\/\/|https:\/\/go.rocket.chat\//, ''); @@ -83,15 +107,17 @@ export default class App extends Component { Navigation.setDefaultOptions({ topBar: { backButton: { - icon: { uri: 'back', scale: Dimensions.get('window').scale } + showTitle: false + }, + leftButtonStyle: { + color: '#FFF' + }, + rightButtonStyle: { + color: '#FFF' }, title: { - color: isAndroid() ? '#FFF' : undefined - }, - background: { - color: isAndroid() ? '#2F343D' : undefined - }, - buttonColor: '#FFF' + fontFamily: Platform.OS === 'ios' ? 'System' : 'sans-serif-medium' + } }, sideMenu: { left: { @@ -121,6 +147,8 @@ export default class App extends Component { startNotLogged(); } else if (root === 'inside') { startLogged(); + } else if (root === 'setUsername') { + startSetUsername(); } } } diff --git a/app/lib/rocketchat.js b/app/lib/rocketchat.js index 92c42788..5cee9833 100644 --- a/app/lib/rocketchat.js +++ b/app/lib/rocketchat.js @@ -11,7 +11,7 @@ import log from '../utils/log'; // import * as actions from '../actions'; import { - setUser, setLoginServices, removeLoginServices, loginRequest, loginSuccess, loginFailure, logout + setUser, setLoginServices, loginRequest, loginSuccess, loginFailure, logout } from '../actions/login'; import { disconnect, connectSuccess } from '../actions/connect'; import { setActiveUser } from '../actions/activeUsers'; @@ -125,18 +125,34 @@ const RocketChat = { } }, async loginSuccess(user) { - try { - if (!user) { - const { user: u } = reduxStore.getState().login; - user = Object.assign({}, u); - } + if (!user) { + const { user: u } = reduxStore.getState().login; + user = Object.assign({}, u); + } - // TODO: one api call - // call /me only one time + // TODO: one api call + // call /me only one time + try { if (!user.username) { - const me = await SDK.api.get('me'); + // get me from api + let me = await SDK.api.get('me'); + // if server didn't found username + if (!me.username) { + // search username from credentials (sent during registerSubmit) + const { username } = reduxStore.getState().login.credentials; + if (username) { + // set username + await RocketChat.setUsername({ username }); + me = { ...me, username }; + } + } user = { ...user, ...me }; } + } catch (e) { + log('SDK.loginSuccess set username', e); + } + + try { if (user.username) { const userInfo = await SDK.api.get('users.info', { userId: user.id }); user = { ...user, ...userInfo.user }; @@ -362,28 +378,6 @@ const RocketChat = { } })); - SDK.driver.on('meteor_accounts_loginServiceConfiguration', (error, ddpMessage) => { - if (ddpMessage.msg === 'added') { - this.loginServices = this.loginServices || {}; - if (this.loginServiceTimer) { - clearTimeout(this.loginServiceTimer); - this.loginServiceTimer = null; - } - this.loginServiceTimer = setTimeout(() => { - reduxStore.dispatch(setLoginServices(this.loginServices)); - this.loginServiceTimer = null; - return this.loginServices = {}; - }, 1000); - this.loginServices[ddpMessage.fields.service] = { ...ddpMessage.fields }; - delete this.loginServices[ddpMessage.fields.service].service; - } else if (ddpMessage.msg === 'removed') { - if (this.loginServiceTimer) { - clearTimeout(this.loginServiceTimer); - } - this.loginServiceTimer = setTimeout(() => reduxStore.dispatch(removeLoginServices()), 1000); - } - }); - SDK.driver.on('rocketchat_roles', protectedFunction((error, ddpMessage) => { this.roles = this.roles || {}; @@ -432,8 +426,8 @@ const RocketChat = { return call('registerUser', credentials); }, - setUsername({ credentials }) { - return call('setUsername', credentials.username); + setUsername({ username }) { + return call('setUsername', username); }, forgotPassword(email) { @@ -622,7 +616,7 @@ const RocketChat = { return setting; }); }, - _filterSettings: settings => settings.filter(setting => defaultSettings[setting._id] && setting.value), + _filterSettings: settings => settings.filter(setting => defaultSettings[setting._id] && (setting.value || setting.valueAsString || setting.valueAsNumber || setting.valueAsBoolean)), parseEmojis: emojis => emojis.reduce((ret, item) => { ret[item.name] = item.extension; item.aliases.forEach((alias) => { @@ -805,6 +799,30 @@ const RocketChat = { } catch (error) { console.warn(error); } + }, + async getLoginServices(server) { + try { + let loginServicesFilter = []; + const loginServicesResult = await fetch(`${ server }/api/v1/settings.oauth`).then(response => response.json()); + // TODO: remove this after SAML and custom oauth + const availableOAuth = ['facebook', 'github', 'gitlab', 'google', 'linkedin', 'meteor-developer', 'twitter']; + if (loginServicesResult.success && loginServicesResult.services.length > 0) { + const { services } = loginServicesResult; + loginServicesFilter = services.filter(item => availableOAuth.includes(item.name)); + const loginServicesReducer = loginServicesFilter.reduce((ret, item) => { + ret[item.name] = item; + return ret; + }, {}); + reduxStore.dispatch(setLoginServices(loginServicesReducer)); + } + return Promise.resolve(loginServicesFilter.length); + } catch (error) { + console.warn(error); + return Promise.reject(); + } + }, + getUsernameSuggestion() { + return SDK.driver.asyncCall('getUsernameSuggestion'); } }; diff --git a/app/presentation/RoomItem.js b/app/presentation/RoomItem.js index 3e39558f..6c16105b 100644 --- a/app/presentation/RoomItem.js +++ b/app/presentation/RoomItem.js @@ -215,7 +215,7 @@ export default class RoomItem extends React.Component { if (type === 'd') { return ; } - return ; + return ; } formatDate = date => moment(date).calendar(null, { diff --git a/app/reducers/login.js b/app/reducers/login.js index cf4d2ff7..ef222d06 100644 --- a/app/reducers/login.js +++ b/app/reducers/login.js @@ -3,11 +3,11 @@ import * as types from '../actions/actionsTypes'; const initialState = { isAuthenticated: false, isFetching: false, - isRegistering: false, token: '', user: {}, error: '', - services: {} + services: {}, + credentials: {} }; export default function login(state = initialState, action) { @@ -19,7 +19,6 @@ export default function login(state = initialState, action) { ...state, isFetching: true, isAuthenticated: false, - isRegistering: false, failure: false, error: '' }; @@ -34,7 +33,8 @@ export default function login(state = initialState, action) { }, token: action.user.token, failure: false, - error: '' + error: '', + credentials: {} }; case types.LOGIN.FAILURE: return { @@ -61,37 +61,29 @@ export default function login(state = initialState, action) { return { ...state, isFetching: true, - isAuthenticated: false, - isRegistering: true, failure: false, - error: '' + error: '', + credentials: action.credentials }; case types.LOGIN.REGISTER_SUCCESS: return { ...state, isFetching: false, - isAuthenticated: false, failure: false, - error: '' + error: '', + credentials: {} }; case types.LOGIN.SET_USERNAME_SUBMIT: return { ...state, - isFetching: true + isFetching: true, + credentials: action.credentials }; case types.LOGIN.SET_USERNAME_SUCCESS: return { ...state, - isFetching: false, - isRegistering: false + isFetching: false }; - case types.LOGIN.REGISTER_INCOMPLETE: - return { - ...state, - isRegistering: true - }; - case types.FORGOT_PASSWORD.INIT: - return initialState; case types.FORGOT_PASSWORD.REQUEST: return { ...state, @@ -128,11 +120,6 @@ export default function login(state = initialState, action) { ...action.data } }; - case types.LOGIN.REMOVE_SERVICES: - return { - ...state, - services: {} - }; case types.LOGIN.SET_PREFERENCE: return { ...state, diff --git a/app/sagas/login.js b/app/sagas/login.js index b1011158..b5981cf3 100644 --- a/app/sagas/login.js +++ b/app/sagas/login.js @@ -1,7 +1,7 @@ import { AsyncStorage } from 'react-native'; import { delay } from 'redux-saga'; import { - put, call, take, takeLatest, select, all + put, call, takeLatest, select, all } from 'redux-saga/effects'; import { Navigation } from 'react-native-navigation'; @@ -9,15 +9,8 @@ import * as types from '../actions/actionsTypes'; import { appStart } from '../actions'; import { serverFinishAdd } from '../actions/server'; import { - // loginRequest, - // loginSubmit, registerRequest, - registerIncomplete, - // loginSuccess, loginFailure, - // logout, - // setToken, - registerSuccess, setUsernameRequest, setUsernameSuccess, forgotPasswordSuccess, @@ -29,7 +22,6 @@ import I18n from '../i18n'; const getUser = state => state.login.user; const getServer = state => state.server.server; -const getIsConnected = state => state.meteor.connected; const loginCall = args => RocketChat.loginWithPassword(args); const registerCall = args => RocketChat.register(args); @@ -43,16 +35,16 @@ const handleLoginSuccess = function* handleLoginSuccess() { const user = yield select(getUser); const adding = yield select(state => state.server.adding); yield AsyncStorage.setItem(RocketChat.TOKEN_KEY, user.token); - if (!user.username || user.isRegistering) { - yield put(registerIncomplete()); + + if (!user.username) { + return yield put(appStart('setUsername')); + } + + if (adding) { + yield put(serverFinishAdd()); + yield Navigation.dismissAllModals(); } else { - yield delay(300); - if (adding) { - yield put(serverFinishAdd()); - yield Navigation.dismissAllModals(); - } else { - yield put(appStart('inside')); - } + yield put(appStart('inside')); } } catch (e) { log('handleLoginSuccess', e); @@ -66,14 +58,6 @@ const handleRegisterSubmit = function* handleRegisterSubmit({ credentials }) { const handleRegisterRequest = function* handleRegisterRequest({ credentials }) { try { yield call(registerCall, { credentials }); - yield put(registerSuccess(credentials)); - } catch (err) { - yield put(loginFailure(err)); - } -}; - -const handleRegisterSuccess = function* handleRegisterSuccess({ credentials }) { - try { yield call(loginCall, { username: credentials.email, password: credentials.pass @@ -89,7 +73,7 @@ const handleSetUsernameSubmit = function* handleSetUsernameSubmit({ credentials const handleSetUsernameRequest = function* handleSetUsernameRequest({ credentials }) { try { - yield call(setUsernameCall, { credentials }); + yield call(setUsernameCall, credentials); yield put(setUsernameSuccess()); yield call(loginSuccessCall); } catch (err) { @@ -109,13 +93,6 @@ const handleLogout = function* handleLogout() { } }; -const handleRegisterIncomplete = function* handleRegisterIncomplete() { - const server = yield select(state => state.server); - if (!server.adding) { - yield put(appStart('outside')); - } -}; - const handleForgotPasswordRequest = function* handleForgotPasswordRequest({ email }) { try { yield call(forgotPasswordCall, email); @@ -125,22 +102,6 @@ const handleForgotPasswordRequest = function* handleForgotPasswordRequest({ emai } }; -const watchLoginOpen = function* watchLoginOpen() { - try { - const isConnected = yield select(getIsConnected); - if (!isConnected) { - yield take(types.METEOR.SUCCESS); - } - const sub = yield RocketChat.subscribe('meteor.loginServiceConfiguration'); - yield take(types.LOGIN.CLOSE); - if (sub) { - yield sub.unsubscribe().catch(err => console.warn(err)); - } - } catch (e) { - log('watchLoginOpen', e); - } -}; - const handleSetUser = function* handleSetUser() { yield delay(2000); const [server, user] = yield all([select(getServer), select(getUser)]); @@ -155,19 +116,13 @@ const handleSetUser = function* handleSetUser() { }; const root = function* root() { - // yield takeLatest(types.METEOR.SUCCESS, handleLoginWhenServerChanges); - // yield takeLatest(types.LOGIN.REQUEST, handleLoginRequest); yield takeLatest(types.LOGIN.SUCCESS, handleLoginSuccess); - // yield takeLatest(types.LOGIN.SUBMIT, handleLoginSubmit); yield takeLatest(types.LOGIN.REGISTER_REQUEST, handleRegisterRequest); yield takeLatest(types.LOGIN.REGISTER_SUBMIT, handleRegisterSubmit); - yield takeLatest(types.LOGIN.REGISTER_SUCCESS, handleRegisterSuccess); - yield takeLatest(types.LOGIN.REGISTER_INCOMPLETE, handleRegisterIncomplete); yield takeLatest(types.LOGIN.SET_USERNAME_SUBMIT, handleSetUsernameSubmit); yield takeLatest(types.LOGIN.SET_USERNAME_REQUEST, handleSetUsernameRequest); yield takeLatest(types.LOGOUT, handleLogout); yield takeLatest(types.FORGOT_PASSWORD.REQUEST, handleForgotPasswordRequest); - yield takeLatest(types.LOGIN.OPEN, watchLoginOpen); yield takeLatest(types.USER.SET, handleSetUser); }; export default root; diff --git a/app/sagas/selectServer.js b/app/sagas/selectServer.js index dadc11dd..9a3d50b4 100644 --- a/app/sagas/selectServer.js +++ b/app/sagas/selectServer.js @@ -2,6 +2,7 @@ import { put, call, takeLatest } from 'redux-saga/effects'; import { AsyncStorage } from 'react-native'; import { Navigation } from 'react-native-navigation'; import { Provider } from 'react-redux'; +import { gestureHandlerRootHOC } from 'react-native-gesture-handler'; import { SERVER } from '../actions/actionsTypes'; import * as actions from '../actions'; @@ -14,10 +15,7 @@ import log from '../utils/log'; import store from '../lib/createStore'; let LoginSignupView = null; - -const validate = function* validate(server) { - return yield RocketChat.testServer(server); -}; +let LoginView = null; const handleSelectServer = function* handleSelectServer({ server }) { try { @@ -29,7 +27,7 @@ const handleSelectServer = function* handleSelectServer({ server }) { } const settings = database.objects('settings'); - yield put(actions.setAllSettings(RocketChat.parseSettings(settings.slice(0, settings.length)))); + yield put(actions.setAllSettings(RocketChat.parseSettings(RocketChat._filterSettings(settings.slice(0, settings.length))))); const emojis = database.objects('customEmojis'); yield put(actions.setCustomEmojis(RocketChat.parseEmojis(emojis.slice(0, emojis.length)))); const roles = database.objects('roles'); @@ -47,24 +45,29 @@ const handleSelectServer = function* handleSelectServer({ server }) { const handleServerRequest = function* handleServerRequest({ server }) { try { - if (LoginSignupView == null) { - LoginSignupView = require('../views/LoginSignupView').default; - Navigation.registerComponentWithRedux('LoginSignupView', () => LoginSignupView, Provider, store); - } - - yield call(validate, server); - yield Navigation.push('NewServerView', { - component: { - name: 'LoginSignupView', - options: { - topBar: { - title: { - text: server - } - } - } + yield RocketChat.testServer(server); + const loginServicesLength = yield RocketChat.getLoginServices(server); + if (loginServicesLength === 0) { + if (LoginView == null) { + LoginView = require('../views/LoginView').default; + Navigation.registerComponentWithRedux('LoginView', () => gestureHandlerRootHOC(LoginView), Provider, store); } - }); + yield Navigation.push('NewServerView', { + component: { + name: 'LoginView' + } + }); + } else { + if (LoginSignupView == null) { + LoginSignupView = require('../views/LoginSignupView').default; + Navigation.registerComponentWithRedux('LoginSignupView', () => gestureHandlerRootHOC(LoginSignupView), Provider, store); + } + yield Navigation.push('NewServerView', { + component: { + name: 'LoginSignupView' + } + }); + } database.databases.serversDB.write(() => { database.databases.serversDB.create('servers', { id: server }, true); diff --git a/app/views/CreateChannelView.js b/app/views/CreateChannelView.js index be205630..193c1327 100644 --- a/app/views/CreateChannelView.js +++ b/app/views/CreateChannelView.js @@ -17,6 +17,7 @@ import scrollPersistTaps from '../utils/scrollPersistTaps'; import I18n from '../i18n'; import UserItem from '../presentation/UserItem'; import { showErrorAlert } from '../utils/info'; +import { DEFAULT_HEADER } from '../constants/headerOptions'; const styles = StyleSheet.create({ container: { @@ -85,6 +86,19 @@ const styles = StyleSheet.create({ })) /** @extends React.Component */ export default class CreateChannelView extends LoggedView { + static options() { + return { + ...DEFAULT_HEADER, + topBar: { + ...DEFAULT_HEADER.topBar, + title: { + ...DEFAULT_HEADER.topBar.title, + text: I18n.t('Create_Channel') + } + } + }; + } + static propTypes = { componentId: PropTypes.string, baseUrl: PropTypes.string, @@ -109,7 +123,7 @@ export default class CreateChannelView extends LoggedView { } componentDidMount() { - setTimeout(() => { + this.timeout = setTimeout(() => { this.channelNameRef.focus(); }, 600); } @@ -140,6 +154,12 @@ export default class CreateChannelView extends LoggedView { } } + componentWillUnmount() { + if (this.timeout) { + clearTimeout(this.timeout); + } + } + onChangeText = (channelName) => { const { componentId } = this.props; const rightButtons = []; diff --git a/app/views/ForgotPasswordView.js b/app/views/ForgotPasswordView.js index 1d1fc4e5..fc5e0178 100644 --- a/app/views/ForgotPasswordView.js +++ b/app/views/ForgotPasswordView.js @@ -1,32 +1,36 @@ import React from 'react'; import PropTypes from 'prop-types'; -import { Text, View, ScrollView } from 'react-native'; +import { Text, ScrollView } from 'react-native'; import { connect } from 'react-redux'; import { Navigation } from 'react-native-navigation'; import SafeAreaView from 'react-native-safe-area-view'; import LoggedView from './View'; -import { forgotPasswordInit as forgotPasswordInitAction, forgotPasswordRequest as forgotPasswordRequestAction } from '../actions/login'; +import { forgotPasswordRequest as forgotPasswordRequestAction } from '../actions/login'; import KeyboardView from '../presentation/KeyboardView'; import TextInput from '../containers/TextInput'; import Button from '../containers/Button'; -import Loading from '../containers/Loading'; -import styles from './Styles'; +import sharedStyles from './Styles'; import { showErrorAlert } from '../utils/info'; import scrollPersistTaps from '../utils/scrollPersistTaps'; import I18n from '../i18n'; +import { DARK_HEADER } from '../constants/headerOptions'; @connect(state => ({ login: state.login }), dispatch => ({ - forgotPasswordInit: () => dispatch(forgotPasswordInitAction()), forgotPasswordRequest: email => dispatch(forgotPasswordRequestAction(email)) })) /** @extends React.Component */ export default class ForgotPasswordView extends LoggedView { + static options() { + return { + ...DARK_HEADER + }; + } + static propTypes = { componentId: PropTypes.string, - forgotPasswordInit: PropTypes.func.isRequired, forgotPasswordRequest: PropTypes.func.isRequired, login: PropTypes.object } @@ -36,13 +40,14 @@ export default class ForgotPasswordView extends LoggedView { this.state = { email: '', - invalidEmail: false + invalidEmail: true }; } componentDidMount() { - const { forgotPasswordInit } = this.props; - forgotPasswordInit(); + this.timeout = setTimeout(() => { + this.emailInput.focus(); + }, 600); } componentDidUpdate() { @@ -55,6 +60,12 @@ export default class ForgotPasswordView extends LoggedView { } } + componentWillUnmount() { + if (this.timeout) { + clearTimeout(this.timeout); + } + } + validate = (email) => { /* eslint-disable no-useless-escape */ const reg = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; @@ -80,35 +91,31 @@ export default class ForgotPasswordView extends LoggedView { return ( - - - - this.validate(email)} - onSubmitEditing={() => this.resetPassword()} - testID='forgot-password-view-email' - /> - - -