diff --git a/android/app/src/debug/java/chat/rocket/reactnative/MainDebugApplication.java b/android/app/src/debug/java/chat/rocket/reactnative/MainDebugApplication.java deleted file mode 100644 index e6abf3b05..000000000 --- a/android/app/src/debug/java/chat/rocket/reactnative/MainDebugApplication.java +++ /dev/null @@ -1,25 +0,0 @@ -package chat.rocket.reactnative; - -import android.content.Context; - -import com.facebook.react.ReactInstanceManager; - -public class MainDebugApplication extends MainApplication { - - @Override - public void onCreate() { - super.onCreate(); - initializeFlipper(this, getReactNativeHost().getReactInstanceManager()); - } - - /** - * Loads Flipper in React Native templates. Call this in the onCreate method with something like - * initializeFlipper(this, getReactNativeHost().getReactInstanceManager()); - * - * @param context - * @param reactInstanceManager - */ - private static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) { - ReactNativeFlipper.initializeFlipper(context, reactInstanceManager); - } -} diff --git a/android/app/src/main/java/chat/rocket/reactnative/MainApplication.java b/android/app/src/main/java/chat/rocket/reactnative/MainApplication.java index 871e6e86d..b94159e09 100644 --- a/android/app/src/main/java/chat/rocket/reactnative/MainApplication.java +++ b/android/app/src/main/java/chat/rocket/reactnative/MainApplication.java @@ -9,13 +9,16 @@ import com.facebook.react.ReactApplication; import com.facebook.react.ReactNativeHost; import com.facebook.react.ReactPackage; import com.facebook.react.config.ReactFeatureFlags; +import com.facebook.react.ReactInstanceManager; import com.facebook.soloader.SoLoader; import com.reactnativecommunity.viewpager.RNCViewPagerPackage; import com.facebook.react.bridge.JSIModulePackage; import com.swmansion.reanimated.ReanimatedJSIModulePackage; +import android.content.Context; import android.content.res.Configuration; import expo.modules.ApplicationLifecycleDispatcher; import expo.modules.ReactNativeHostWrapper; +import java.lang.reflect.InvocationTargetException; import java.util.Arrays; import java.util.List; @@ -76,6 +79,7 @@ public class MainApplication extends Application implements ReactApplication { // If you opted-in for the New Architecture, we enable the TurboModule system ReactFeatureFlags.useTurboModules = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED; SoLoader.init(this, /* native exopackage */ false); + initializeFlipper(this, getReactNativeHost().getReactInstanceManager()); ApplicationLifecycleDispatcher.onApplicationCreate(this); } @@ -84,4 +88,35 @@ public class MainApplication extends Application implements ReactApplication { super.onConfigurationChanged(newConfig); ApplicationLifecycleDispatcher.onConfigurationChanged(this, newConfig); } + + /** + * Loads Flipper in React Native templates. Call this in the onCreate method with something like + * initializeFlipper(this, getReactNativeHost().getReactInstanceManager()); + * + * @param context + * @param reactInstanceManager + */ + private static void initializeFlipper( + Context context, ReactInstanceManager reactInstanceManager) { + if (BuildConfig.DEBUG) { + try { + /* + We use reflection here to pick up the class that initializes Flipper, + since Flipper library is not available in release mode + */ + Class aClass = Class.forName("chat.rocket.reactnative.ReactNativeFlipper"); + aClass + .getMethod("initializeFlipper", Context.class, ReactInstanceManager.class) + .invoke(null, context, reactInstanceManager); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } catch (NoSuchMethodException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } catch (InvocationTargetException e) { + e.printStackTrace(); + } + } + } } diff --git a/android/gradle.properties b/android/gradle.properties index 59600f62e..29d16769c 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -23,7 +23,7 @@ android.useAndroidX=true android.enableJetifier=true # Version of flipper SDK to use with React Native -FLIPPER_VERSION=0.125.0 +FLIPPER_VERSION=0.175.0 # Use this property to specify which architecture you want to build. # You can also override it from the CLI using diff --git a/app/definitions/IUpload.ts b/app/definitions/IUpload.ts index 059555130..52d3c1995 100644 --- a/app/definitions/IUpload.ts +++ b/app/definitions/IUpload.ts @@ -5,6 +5,7 @@ export interface IUpload { rid?: string; path: string; name?: string; + tmid?: string; description?: string; size: number; type?: string; diff --git a/app/lib/database/model/Upload.js b/app/lib/database/model/Upload.js index d03a87729..a96e2c995 100644 --- a/app/lib/database/model/Upload.js +++ b/app/lib/database/model/Upload.js @@ -16,6 +16,8 @@ export default class Upload extends Model { @field('name') name; + @field('tmid') tmid; + @field('description') description; @field('size') size; diff --git a/app/lib/database/model/migrations.js b/app/lib/database/model/migrations.js index aacbd5903..3a5374e56 100644 --- a/app/lib/database/model/migrations.js +++ b/app/lib/database/model/migrations.js @@ -239,6 +239,15 @@ export default schemaMigrations({ columns: [{ name: 'hide_mention_status', type: 'boolean', isOptional: true }] }) ] + }, + { + toVersion: 19, + steps: [ + addColumns({ + table: 'uploads', + columns: [{ name: 'tmid', type: 'string', isOptional: true }] + }) + ] } ] }); diff --git a/app/lib/database/schema/app.js b/app/lib/database/schema/app.js index 6380084af..f354b34eb 100644 --- a/app/lib/database/schema/app.js +++ b/app/lib/database/schema/app.js @@ -1,7 +1,7 @@ import { appSchema, tableSchema } from '@nozbe/watermelondb'; export default appSchema({ - version: 18, + version: 19, tables: [ tableSchema({ name: 'subscriptions', @@ -222,6 +222,7 @@ export default appSchema({ { name: 'path', type: 'string', isOptional: true }, { name: 'rid', type: 'string', isIndexed: true }, { name: 'name', type: 'string', isOptional: true }, + { name: 'tmid', type: 'string', isOptional: true }, { name: 'description', type: 'string', isOptional: true }, { name: 'size', type: 'number' }, { name: 'type', type: 'string', isOptional: true }, diff --git a/app/lib/methods/sendFileMessage.ts b/app/lib/methods/sendFileMessage.ts index dbbe6317e..08033cb60 100644 --- a/app/lib/methods/sendFileMessage.ts +++ b/app/lib/methods/sendFileMessage.ts @@ -46,7 +46,8 @@ export function sendFileMessage( fileInfo: IUpload, tmid: string | undefined, server: string, - user: Partial> + user: Partial>, + isForceTryAgain?: boolean ): Promise { return new Promise(async (resolve, reject) => { try { @@ -62,7 +63,7 @@ export function sendFileMessage( let uploadRecord: TUploadModel; try { uploadRecord = await uploadsCollection.find(uploadPath); - if (uploadRecord.id) { + if (uploadRecord.id && !isForceTryAgain) { return Alert.alert(i18n.t('FileUpload_Error'), i18n.t('Upload_in_progress')); } } catch (error) { @@ -71,6 +72,9 @@ export function sendFileMessage( uploadRecord = await uploadsCollection.create(u => { u._raw = sanitizedRaw({ id: uploadPath }, uploadsCollection.schema); Object.assign(u, fileInfo); + if (tmid) { + u.tmid = tmid; + } if (u.subscription) { u.subscription.id = rid; } diff --git a/app/lib/notifications/index.ts b/app/lib/notifications/index.ts index 3d4888987..167add557 100644 --- a/app/lib/notifications/index.ts +++ b/app/lib/notifications/index.ts @@ -3,7 +3,7 @@ import EJSON from 'ejson'; import { store } from '../store/auxStore'; import { deepLinkingOpen } from '../../actions/deepLinking'; import { isFDroidBuild } from '../constants'; -import { deviceToken, pushNotificationConfigure, setNotificationsBadgeCount } from './push'; +import { deviceToken, pushNotificationConfigure, setNotificationsBadgeCount, removeAllNotifications } from './push'; import { INotification, SubscriptionType } from '../../definitions'; interface IEjson { @@ -49,6 +49,10 @@ export const onNotification = (push: INotification): void => { export const getDeviceToken = (): string => deviceToken; export const setBadgeCount = (count?: number): void => setNotificationsBadgeCount(count); +export const removeNotificationsAndBadge = () => { + removeAllNotifications(); + setBadgeCount(); +}; export const initializePushNotifications = (): Promise | undefined => { if (!isFDroidBuild) { setBadgeCount(); diff --git a/app/lib/notifications/push.ts b/app/lib/notifications/push.ts index 4da3c1a62..4515da941 100644 --- a/app/lib/notifications/push.ts +++ b/app/lib/notifications/push.ts @@ -21,6 +21,10 @@ export const setNotificationsBadgeCount = (count = 0): void => { } }; +export const removeAllNotifications = (): void => { + Notifications.removeAllDeliveredNotifications(); +}; + export const pushNotificationConfigure = (onNotification: (notification: INotification) => void): Promise => { if (isIOS) { // init diff --git a/app/lib/store/appStateMiddleware.ts b/app/lib/store/appStateMiddleware.ts index 7025a8191..61da57a6c 100644 --- a/app/lib/store/appStateMiddleware.ts +++ b/app/lib/store/appStateMiddleware.ts @@ -1,6 +1,7 @@ // https://github.com/bamlab/redux-enhancer-react-native-appstate import { AppState } from 'react-native'; +import { removeNotificationsAndBadge } from '../notifications'; import { APP_STATE } from '../../actions/actionsTypes'; export default () => @@ -16,6 +17,7 @@ export default () => let type; if (nextAppState === 'active') { type = APP_STATE.FOREGROUND; + removeNotificationsAndBadge(); } else if (nextAppState === 'background') { type = APP_STATE.BACKGROUND; } diff --git a/app/sagas/state.js b/app/sagas/state.js index b29b2645a..1e6bcddab 100644 --- a/app/sagas/state.js +++ b/app/sagas/state.js @@ -5,7 +5,6 @@ import { localAuthenticate, saveLastLocalAuthenticationSession } from '../lib/me import { APP_STATE } from '../actions/actionsTypes'; import { RootEnum } from '../definitions'; import { Services } from '../lib/services'; -import { setBadgeCount } from '../lib/notifications'; const appHasComeBackToForeground = function* appHasComeBackToForeground() { const appRoot = yield select(state => state.app.root); @@ -20,7 +19,6 @@ const appHasComeBackToForeground = function* appHasComeBackToForeground() { try { yield localAuthenticate(server.server); Services.checkAndReopen(); - setBadgeCount(); return yield Services.setUserPresenceOnline(); } catch (e) { log(e); diff --git a/app/views/RoomView/UploadProgress.tsx b/app/views/RoomView/UploadProgress.tsx index 2509870c9..6c78ef204 100644 --- a/app/views/RoomView/UploadProgress.tsx +++ b/app/views/RoomView/UploadProgress.tsx @@ -160,7 +160,7 @@ class UploadProgress extends Component { const [preferences, setPreferences] = useState({} as INotificationPreferences); - const [loading, setLoading] = useState(false); + const [loading, setLoading] = useState(true); const navigation = useNavigation>(); const userId = useAppSelector(state => getUserSelector(state).id); @@ -33,10 +33,11 @@ const UserNotificationPreferencesView = () => { try { const result = await Services.getUserPreferences(userId); if (result.success) { - setLoading(true); + setLoading(false); setPreferences(result.preferences); } } catch (error) { + setLoading(false); log(error); } } @@ -63,6 +64,8 @@ const UserNotificationPreferencesView = () => { {loading ? ( + + ) : ( <> @@ -103,8 +106,6 @@ const UserNotificationPreferencesView = () => { - ) : ( - )} diff --git a/e2e/tests/assorted/14-in-app-notification.spec.ts b/e2e/tests/assorted/14-in-app-notification.spec.ts index 505f12494..23381e787 100644 --- a/e2e/tests/assorted/14-in-app-notification.spec.ts +++ b/e2e/tests/assorted/14-in-app-notification.spec.ts @@ -32,8 +32,9 @@ describe('InApp Notification', () => { .withTimeout(2000); await sleep(500); await element(by.id(`in-app-notification-${text}`)).tap(); - await sleep(500); - await expect(element(by.id('room-header'))).toExist(); + await waitFor(element(by.id('room-view'))) + .toBeVisible() + .withTimeout(5000); await expect(element(by.id(`room-view-title-${data.users.alternate.username}`))).toExist(); }); }); diff --git a/ios/Podfile.lock b/ios/Podfile.lock index d8294072a..e412a206c 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -503,7 +503,7 @@ PODS: - React-Core - RNDateTimePicker (3.5.2): - React-Core - - RNDeviceInfo (8.4.8): + - RNDeviceInfo (10.3.0): - React-Core - RNFastImage (8.5.12): - React-Core @@ -982,7 +982,7 @@ SPEC CHECKSUMS: RNConfigReader: 396da6a6444182a76e8ae0930b9436c7575045cb RNCPicker: 914b557e20b3b8317b084aca9ff4b4edb95f61e4 RNDateTimePicker: 7658208086d86d09e1627b5c34ba0cf237c60140 - RNDeviceInfo: 0400a6d0c94186d1120c3cbd97b23abc022187a9 + RNDeviceInfo: 4701f0bf2a06b34654745053db0ce4cb0c53ada7 RNFastImage: d5510534be9cccc80e824bfec6369c116d212871 RNFBAnalytics: 091c8adcbb0da1e1680ce434fc6e8a0a501fe2e6 RNFBApp: b1b5a80a676a07dea17e778bda7c1e8b69b2f5ec diff --git a/package.json b/package.json index c02f8cbf7..506425329 100644 --- a/package.json +++ b/package.json @@ -87,7 +87,7 @@ "react-native-bootsplash": "^4.3.3", "react-native-config-reader": "^4.1.1", "react-native-console-time-polyfill": "1.2.3", - "react-native-device-info": "8.4.8", + "react-native-device-info": "^10.3.0", "react-native-document-picker": "^8.1.2", "react-native-easy-grid": "^0.2.2", "react-native-easy-toast": "^1.2.0", diff --git a/patches/react-native-device-info+8.4.8.patch b/patches/react-native-device-info+10.3.0.patch similarity index 100% rename from patches/react-native-device-info+8.4.8.patch rename to patches/react-native-device-info+10.3.0.patch diff --git a/yarn.lock b/yarn.lock index 4f3e5d74e..602af3e80 100644 --- a/yarn.lock +++ b/yarn.lock @@ -14126,9 +14126,9 @@ loader-utils@2.0.0, loader-utils@^2.0.0: json5 "^2.1.2" loader-utils@^1.2.3: - version "1.4.1" - resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.1.tgz#278ad7006660bccc4d2c0c1578e17c5c78d5c0e0" - integrity sha512-1Qo97Y2oKaU+Ro2xnDMR26g1BwMT29jNbem1EvcujW2jqt+j5COXyscjM7bLQkM9HaxI7pkWeW7gnI072yMI9Q== + version "1.4.2" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.2.tgz#29a957f3a63973883eb684f10ffd3d151fec01a3" + integrity sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg== dependencies: big.js "^5.2.2" emojis-list "^3.0.0" @@ -15015,21 +15015,11 @@ minimatch@3.0.4: dependencies: brace-expansion "^1.1.7" -minimist@^1.1.1, minimist@^1.2.5, "minimist@~ 1.2.0": - version "1.2.5" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" - integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== - -minimist@^1.2.0: +minimist@^1.1.1, minimist@^1.2.0, minimist@^1.2.5, minimist@^1.2.6, "minimist@~ 1.2.0": version "1.2.7" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.7.tgz#daa1c4d91f507390437c6a8bc01078e7000c4d18" integrity sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g== -minimist@^1.2.6: - version "1.2.6" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" - integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== - minipass-collect@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/minipass-collect/-/minipass-collect-1.0.2.tgz#22b813bf745dc6edba2576b940022ad6edc8c617" @@ -17100,10 +17090,10 @@ react-native-console-time-polyfill@1.2.3: resolved "https://registry.yarnpkg.com/react-native-console-time-polyfill/-/react-native-console-time-polyfill-1.2.3.tgz#1039dab1bb9e2d8040f5e19de68e0da781dc9b60" integrity sha512-C7CUb1c6GsCssqvjtRuqVqnGwlfEHXxXDvCUuGNbq/gpZZt+9YbZD3ODmXBDxis3tDQA0k1lbT1VMTqWQw9rDg== -react-native-device-info@8.4.8: - version "8.4.8" - resolved "https://registry.yarnpkg.com/react-native-device-info/-/react-native-device-info-8.4.8.tgz#fc92ae423e47db6cfbf30c30012e09cee63727fa" - integrity sha512-92676ZWHZHsPM/EW1ulgb2MuVfjYfMWRTWMbLcrCsipkcMaZ9Traz5mpsnCS7KZpsOksnvUinzDIjsct2XGc6Q== +react-native-device-info@^10.3.0: + version "10.3.0" + resolved "https://registry.yarnpkg.com/react-native-device-info/-/react-native-device-info-10.3.0.tgz#6bab64d84d3415dd00cc446c73ec5e2e61fddbe7" + integrity sha512-/ziZN1sA1REbJTv5mQZ4tXggcTvSbct+u5kCaze8BmN//lbxcTvWsU6NQd4IihLt89VkbX+14IGc9sVApSxd/w== react-native-document-picker@^8.1.2: version "8.1.2" @@ -19959,9 +19949,9 @@ unbox-primitive@^1.0.2: which-boxed-primitive "^1.0.2" underscore@^1.8.3: - version "1.10.2" - resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.10.2.tgz#73d6aa3668f3188e4adb0f1943bd12cfd7efaaaf" - integrity sha512-N4P+Q/BuyuEKFJ43B9gYuOj4TQUHXX+j2FqguVOpjkssLUUrnJofCcBccJSCoeturDoZU6GorDTHSvUDlSQbTg== + version "1.13.6" + resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.13.6.tgz#04786a1f589dc6c09f761fc5f45b89e935136441" + integrity sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A== unfetch@^4.2.0: version "4.2.0"