* Use AppGroupId from Info.plists instead of hardcoded constant
* Update script, ci & Makefile
* Update Cocoapods to 1.9.3
* Split android builds using ABI filters
* Update Fastlane deps & build scripts
* Update CI to use latests scripts
* Display app version & build number in select server screen
* Make generate scripts compatible with node < 12
* Build scripts
* add build script to package.json
* Update to use bundler 2.1.4 and CI with Xcode 12
* Fix script name for build:ios-unsigned
* Fix RN iOS scripts
* Update CI pods-dependencies step
* Add pipefail to android executor
* Update Fastlane
* Fix type in postinstall script
* update android executor and set TERM
* Fix S3 bucket name variable
* Apply suggestions from code review
Co-authored-by: Miguel Alatzar <migbot@users.noreply.github.com>
* Fix master unit tests
* use requireActual in jest setup
* Jest setup to use react instead of React
Co-authored-by: Miguel Alatzar <migbot@users.noreply.github.com>
(cherry picked from commit 30d4aa2a3e)
Co-authored-by: Elias Nahum <nahumhbl@gmail.com>
This commit is contained in:
parent
768e2f1b84
commit
f23190cf29
63 changed files with 586 additions and 674 deletions
|
|
@ -13,7 +13,7 @@ executors:
|
|||
NODE_ENV: production
|
||||
BABEL_ENV: production
|
||||
docker:
|
||||
- image: circleci/android:api-27-node
|
||||
- image: circleci/android:api-29-node
|
||||
working_directory: ~/mattermost-mobile
|
||||
resource_class: <<parameters.resource_class>>
|
||||
|
||||
|
|
@ -23,7 +23,7 @@ executors:
|
|||
NODE_ENV: production
|
||||
BABEL_ENV: production
|
||||
macos:
|
||||
xcode: "11.0.0"
|
||||
xcode: "12.0.0"
|
||||
working_directory: ~/mattermost-mobile
|
||||
shell: /bin/bash --login -o pipefail
|
||||
|
||||
|
|
@ -44,7 +44,6 @@ commands:
|
|||
for:
|
||||
type: string
|
||||
steps:
|
||||
- ruby-setup
|
||||
- restore_cache:
|
||||
name: Restore Fastlane cache
|
||||
key: v1-gems-<< parameters.for >>-{{ checksum "fastlane/Gemfile.lock" }}-{{ arch }}
|
||||
|
|
@ -82,7 +81,7 @@ commands:
|
|||
key: v1-assets-{{ checksum "assets/base/config.json" }}-{{ arch }}
|
||||
- run:
|
||||
name: Generate assets
|
||||
command: make dist/assets
|
||||
command: node ./scripts/generate-assets.js
|
||||
- save_cache:
|
||||
name: Save assets cache
|
||||
key: v1-assets-{{ checksum "assets/base/config.json" }}-{{ arch }}
|
||||
|
|
@ -104,8 +103,8 @@ commands:
|
|||
paths:
|
||||
- node_modules
|
||||
- run:
|
||||
name: "Run post install scripts"
|
||||
command: make post-install
|
||||
name: "Patch dependencies"
|
||||
command: npx patch-package
|
||||
|
||||
pods-dependencies:
|
||||
description: "Get cocoapods dependencies"
|
||||
|
|
@ -113,10 +112,12 @@ commands:
|
|||
- restore_cache:
|
||||
name: Restore cocoapods specs and pods
|
||||
key: v1-cocoapods-{{ checksum "ios/Podfile.lock" }}-{{ arch }}
|
||||
- run:
|
||||
name: iOS gems
|
||||
command: npm run ios-gems
|
||||
- run:
|
||||
name: Getting cocoapods dependencies
|
||||
working_directory: ios
|
||||
command: pod install
|
||||
command: npm run pod-install
|
||||
- save_cache:
|
||||
name: Save cocoapods specs and pods cache
|
||||
key: v1-cocoapods-{{ checksum "ios/Podfile.lock" }}-{{ arch }}
|
||||
|
|
@ -143,11 +144,14 @@ commands:
|
|||
echo MATTERMOST_RELEASE_STORE_FILE=${STORE_FILE} | tee -a android/gradle.properties > /dev/null
|
||||
echo ${STORE_ALIAS} | tee -a android/gradle.properties > /dev/null
|
||||
echo ${STORE_PASSWORD} | tee -a android/gradle.properties > /dev/null
|
||||
- run:
|
||||
name: Jetify android libraries
|
||||
command: ./node_modules/.bin/jetify
|
||||
- run:
|
||||
working_directory: fastlane
|
||||
name: Run fastlane to build android
|
||||
no_output_timeout: 30m
|
||||
command: bundle exec fastlane android build
|
||||
command: export TERM=xterm && bundle exec fastlane android build
|
||||
|
||||
build-ios:
|
||||
description: "Build the iOS app"
|
||||
|
|
@ -165,7 +169,7 @@ commands:
|
|||
no_output_timeout: 30m
|
||||
command: |
|
||||
HOMEBREW_NO_AUTO_UPDATE=1 brew install watchman
|
||||
bundle exec fastlane ios build
|
||||
export TERM=xterm && bundle exec fastlane ios build
|
||||
|
||||
deploy-to-store:
|
||||
description: "Deploy build to store"
|
||||
|
|
@ -201,12 +205,6 @@ commands:
|
|||
- store_artifacts:
|
||||
path: ~/mattermost-mobile/<<parameters.filename>>
|
||||
|
||||
ruby-setup:
|
||||
steps:
|
||||
- run:
|
||||
name: Set Ruby Version
|
||||
command: echo "ruby-2.6.3" > ~/.ruby-version
|
||||
|
||||
jobs:
|
||||
test:
|
||||
working_directory: ~/mattermost-mobile
|
||||
|
|
@ -225,19 +223,7 @@ jobs:
|
|||
command: npm test
|
||||
- run:
|
||||
name: Check i18n
|
||||
command: |
|
||||
mkdir -p tmp
|
||||
cp assets/base/i18n/en.json tmp/en.json
|
||||
mkdir -p tmp/fake-webapp-dir/i18n/
|
||||
echo '{}' > tmp/fake-webapp-dir/i18n/en.json
|
||||
|
||||
npm run mmjstool -- i18n extract-mobile --webapp-dir tmp/fake-webapp-dir --mobile-dir .
|
||||
diff tmp/en.json assets/base/i18n/en.json
|
||||
# Address weblate behavior which does not remove whole translation item when translation string is set to empty
|
||||
npm run mmjstool -- i18n clean-empty --webapp-dir tmp/fake-webapp-dir --mobile-dir . --check
|
||||
|
||||
rm -rf tmp
|
||||
|
||||
command: ./scripts/precommit/i18n.sh
|
||||
|
||||
check-deps:
|
||||
parameters:
|
||||
|
|
@ -297,7 +283,7 @@ jobs:
|
|||
- build-android
|
||||
- persist
|
||||
- save:
|
||||
filename: "Mattermost_Beta.apk"
|
||||
filename: "*.apk"
|
||||
|
||||
build-android-release:
|
||||
executor: android
|
||||
|
|
@ -305,7 +291,7 @@ jobs:
|
|||
- build-android
|
||||
- persist
|
||||
- save:
|
||||
filename: "Mattermost.apk"
|
||||
filename: "*.apk"
|
||||
|
||||
build-android-pr:
|
||||
executor: android
|
||||
|
|
@ -314,7 +300,7 @@ jobs:
|
|||
steps:
|
||||
- build-android
|
||||
- save:
|
||||
filename: "Mattermost_Beta.apk"
|
||||
filename: "*.apk"
|
||||
|
||||
build-android-unsigned:
|
||||
executor: android
|
||||
|
|
@ -326,6 +312,9 @@ jobs:
|
|||
- fastlane-dependencies:
|
||||
for: android
|
||||
- gradle-dependencies
|
||||
- run:
|
||||
name: Jetify Android libraries
|
||||
command: ./node_modules/.bin/jetify
|
||||
- run:
|
||||
working_directory: fastlane
|
||||
name: Run fastlane to build unsigned android
|
||||
|
|
@ -333,7 +322,7 @@ jobs:
|
|||
command: bundle exec fastlane android unsigned
|
||||
- persist
|
||||
- save:
|
||||
filename: "Mattermost-unsigned.apk"
|
||||
filename: "*.apk"
|
||||
|
||||
build-ios-beta:
|
||||
executor: ios
|
||||
|
|
@ -341,7 +330,7 @@ jobs:
|
|||
- build-ios
|
||||
- persist
|
||||
- save:
|
||||
filename: "Mattermost_Beta.ipa"
|
||||
filename: "*.ipa"
|
||||
|
||||
build-ios-release:
|
||||
executor: ios
|
||||
|
|
@ -349,7 +338,7 @@ jobs:
|
|||
- build-ios
|
||||
- persist
|
||||
- save:
|
||||
filename: "Mattermost.ipa"
|
||||
filename: "*.ipa"
|
||||
|
||||
build-ios-pr:
|
||||
executor: ios
|
||||
|
|
@ -358,14 +347,13 @@ jobs:
|
|||
steps:
|
||||
- build-ios
|
||||
- save:
|
||||
filename: "Mattermost_Beta.ipa"
|
||||
filename: "*.ipa"
|
||||
|
||||
build-ios-unsigned:
|
||||
executor: ios
|
||||
steps:
|
||||
- checkout:
|
||||
path: ~/mattermost-mobile
|
||||
- ruby-setup
|
||||
- npm-dependencies
|
||||
- pods-dependencies
|
||||
- assets
|
||||
|
|
@ -381,16 +369,15 @@ jobs:
|
|||
- persist_to_workspace:
|
||||
root: ~/
|
||||
paths:
|
||||
- mattermost-mobile/Mattermost-unsigned.ipa
|
||||
- mattermost-mobile/*.ipa
|
||||
- save:
|
||||
filename: "Mattermost-unsigned.ipa"
|
||||
filename: "*.ipa"
|
||||
|
||||
build-ios-simulator:
|
||||
executor: ios
|
||||
steps:
|
||||
- checkout:
|
||||
path: ~/mattermost-mobile
|
||||
- ruby-setup
|
||||
- npm-dependencies
|
||||
- pods-dependencies
|
||||
- assets
|
||||
|
|
@ -415,47 +402,42 @@ jobs:
|
|||
name: android
|
||||
resource_class: medium
|
||||
steps:
|
||||
- ruby-setup
|
||||
- deploy-to-store:
|
||||
task: "Deploy to Google Play"
|
||||
target: android
|
||||
file: Mattermost.apk
|
||||
file: "*.apk"
|
||||
|
||||
deploy-android-beta:
|
||||
executor:
|
||||
name: android
|
||||
resource_class: medium
|
||||
steps:
|
||||
- ruby-setup
|
||||
- deploy-to-store:
|
||||
task: "Deploy to Google Play"
|
||||
target: android
|
||||
file: Mattermost_Beta.apk
|
||||
file: "*.apk"
|
||||
|
||||
deploy-ios-release:
|
||||
executor: ios
|
||||
steps:
|
||||
- ruby-setup
|
||||
- deploy-to-store:
|
||||
task: "Deploy to TestFlight"
|
||||
target: ios
|
||||
file: Mattermost.ipa
|
||||
file: "*.ipa"
|
||||
|
||||
deploy-ios-beta:
|
||||
executor: ios
|
||||
steps:
|
||||
- ruby-setup
|
||||
- deploy-to-store:
|
||||
task: "Deploy to TestFlight"
|
||||
target: ios
|
||||
file: Mattermost_Beta.ipa
|
||||
file: "*.ipa"
|
||||
|
||||
github-release:
|
||||
executor:
|
||||
name: android
|
||||
resource_class: medium
|
||||
steps:
|
||||
- ruby-setup
|
||||
- attach_workspace:
|
||||
at: ~/
|
||||
- run:
|
||||
|
|
|
|||
232
Makefile
232
Makefile
|
|
@ -1,232 +0,0 @@
|
|||
.PHONY: pre-run pre-build clean
|
||||
.PHONY: check-style
|
||||
.PHONY: start stop
|
||||
.PHONY: run run-ios run-android
|
||||
.PHONY: build build-ios build-android unsigned-ios unsigned-android ios-sim-x86_64
|
||||
.PHONY: build-pr can-build-pr prepare-pr
|
||||
.PHONY: test help
|
||||
|
||||
OS := $(shell sh -c 'uname -s 2>/dev/null')
|
||||
BASE_ASSETS = $(shell find assets/base -type d) $(shell find assets/base -type f -name '*')
|
||||
OVERRIDE_ASSETS = $(shell find assets/override -type d 2> /dev/null) $(shell find assets/override -type f -name '*' 2> /dev/null)
|
||||
MM_UTILITIES_DIR = ../mattermost-utilities
|
||||
|
||||
node_modules: package.json
|
||||
@if ! [ $(shell which npm 2> /dev/null) ]; then \
|
||||
echo "npm is not installed https://npmjs.com"; \
|
||||
exit 1; \
|
||||
fi
|
||||
|
||||
@echo Getting Javascript dependencies
|
||||
@npm install
|
||||
|
||||
npm-ci: package.json
|
||||
@if ! [ $(shell which npm 2> /dev/null) ]; then \
|
||||
echo "npm is not installed https://npmjs.com"; \
|
||||
exit 1; \
|
||||
fi
|
||||
|
||||
@echo Getting Javascript dependencies
|
||||
@npm ci
|
||||
|
||||
.podinstall:
|
||||
ifeq ($(OS), Darwin)
|
||||
@echo "Required version of Cocoapods is not installed"
|
||||
@echo Installing gems;
|
||||
@bundle install
|
||||
@echo Getting Cocoapods dependencies;
|
||||
@cd ios && bundle exec pod install;
|
||||
endif
|
||||
@touch $@
|
||||
|
||||
dist/assets: $(BASE_ASSETS) $(OVERRIDE_ASSETS)
|
||||
@mkdir -p dist
|
||||
|
||||
@if [ -e dist/assets ] ; then \
|
||||
rm -rf dist/assets; \
|
||||
fi
|
||||
|
||||
@echo "Generating app assets"
|
||||
@node scripts/make-dist-assets.js
|
||||
|
||||
pre-run: | node_modules .podinstall dist/assets ## Installs dependencies and assets
|
||||
|
||||
pre-build: | npm-ci .podinstall dist/assets ## Install dependencies and assets before building
|
||||
|
||||
check-style: node_modules ## Runs eslint
|
||||
@echo Checking for style guide compliance
|
||||
@npm run check
|
||||
|
||||
clean: ## Cleans dependencies, previous builds and temp files
|
||||
@echo Cleaning started
|
||||
|
||||
@rm -f .podinstall
|
||||
@rm -rf ios/Pods
|
||||
@rm -rf node_modules
|
||||
@rm -rf dist
|
||||
@rm -rf ios/build
|
||||
@rm -rf android/app/build
|
||||
|
||||
@echo Cleanup finished
|
||||
|
||||
post-install:
|
||||
@./node_modules/.bin/patch-package
|
||||
@./node_modules/.bin/jetify
|
||||
|
||||
@rm -f node_modules/intl/.babelrc
|
||||
@# Hack to get react-intl and its dependencies to work with react-native
|
||||
@# Based off of https://github.com/este/este/blob/master/gulp/native-fix.js
|
||||
@sed -i'' -e 's|"./locale-data/index.js": false|"./locale-data/index.js": "./locale-data/index.js"|g' node_modules/react-intl/package.json
|
||||
@sed -i'' -e 's|"./lib/locales": false|"./lib/locales": "./lib/locales"|g' node_modules/intl-messageformat/package.json
|
||||
@sed -i'' -e 's|"./lib/locales": false|"./lib/locales": "./lib/locales"|g' node_modules/intl-relativeformat/package.json
|
||||
@sed -i'' -e 's|"./locale-data/complete.js": false|"./locale-data/complete.js": "./locale-data/complete.js"|g' node_modules/intl/package.json
|
||||
|
||||
start: | pre-run ## Starts the React Native packager server
|
||||
$(call start_packager)
|
||||
|
||||
stop: ## Stops the React Native packager server
|
||||
$(call stop_packager)
|
||||
|
||||
check-device-ios:
|
||||
@if ! [ $(shell which xcodebuild) ]; then \
|
||||
echo "xcode is not installed"; \
|
||||
exit 1; \
|
||||
fi
|
||||
@if ! [ $(shell which watchman) ]; then \
|
||||
echo "watchman is not installed"; \
|
||||
exit 1; \
|
||||
fi
|
||||
|
||||
check-device-android:
|
||||
@if ! [ $(ANDROID_HOME) ]; then \
|
||||
echo "ANDROID_HOME is not set"; \
|
||||
exit 1; \
|
||||
fi
|
||||
@if ! [ $(shell which adb 2> /dev/null) ]; then \
|
||||
echo "adb is not installed"; \
|
||||
exit 1; \
|
||||
fi
|
||||
|
||||
@echo "Connect your Android device or open the emulator"
|
||||
@adb wait-for-device
|
||||
|
||||
@if ! [ $(shell which watchman 2> /dev/null) ]; then \
|
||||
echo "watchman is not installed"; \
|
||||
exit 1; \
|
||||
fi
|
||||
|
||||
prepare-android-build:
|
||||
@rm -rf ./node_modules/react-native/local-cli/templates/HelloWorld
|
||||
@rm -rf ./node_modules/react-native-linear-gradient/Examples/
|
||||
@rm -rf ./node_modules/react-native-orientation/demo/
|
||||
|
||||
run: run-ios ## alias for run-ios
|
||||
|
||||
run-ios: | check-device-ios pre-run ## Runs the app on an iOS simulator
|
||||
@if [ $(shell ps -ef | grep -i "cli.js start" | grep -civ grep) -eq 0 ]; then \
|
||||
echo Starting React Native packager server; \
|
||||
npm start & echo Running iOS app in development; \
|
||||
if [ ! -z "${SIMULATOR}" ]; then \
|
||||
react-native run-ios --simulator="${SIMULATOR}"; \
|
||||
else \
|
||||
react-native run-ios; \
|
||||
fi; \
|
||||
wait; \
|
||||
else \
|
||||
echo Running iOS app in development; \
|
||||
if [ ! -z "${SIMULATOR}" ]; then \
|
||||
react-native run-ios --simulator="${SIMULATOR}"; \
|
||||
else \
|
||||
react-native run-ios; \
|
||||
fi; \
|
||||
fi
|
||||
|
||||
run-android: | check-device-android pre-run prepare-android-build ## Runs the app on an Android emulator or dev device
|
||||
@if [ $(shell ps -ef | grep -i "cli.js start" | grep -civ grep) -eq 0 ]; then \
|
||||
echo Starting React Native packager server; \
|
||||
npm start & echo Running Android app in development; \
|
||||
if [ ! -z ${VARIANT} ]; then \
|
||||
react-native run-android --no-packager --variant=${VARIANT}; \
|
||||
else \
|
||||
react-native run-android --no-packager; \
|
||||
fi; \
|
||||
wait; \
|
||||
else \
|
||||
echo Running Android app in development; \
|
||||
if [ ! -z ${VARIANT} ]; then \
|
||||
react-native run-android --no-packager --variant=${VARIANT}; \
|
||||
else \
|
||||
react-native run-android --no-packager; \
|
||||
fi; \
|
||||
fi
|
||||
|
||||
build: | stop pre-build check-style ## Builds the app for Android & iOS
|
||||
$(call start_packager)
|
||||
@echo "Building App"
|
||||
@cd fastlane && BABEL_ENV=production NODE_ENV=production bundle exec fastlane build
|
||||
$(call stop_packager)
|
||||
|
||||
|
||||
build-ios: | stop pre-build check-style ## Builds the iOS app
|
||||
$(call start_packager)
|
||||
@echo "Building iOS app"
|
||||
@cd fastlane && BABEL_ENV=production NODE_ENV=production bundle exec fastlane ios build
|
||||
$(call stop_packager)
|
||||
|
||||
build-android: | stop pre-build check-style prepare-android-build ## Build the Android app
|
||||
$(call start_packager)
|
||||
@echo "Building Android app"
|
||||
@cd fastlane && BABEL_ENV=production NODE_ENV=production bundle exec fastlane android build
|
||||
$(call stop_packager)
|
||||
|
||||
unsigned-ios: stop pre-build check-style ## Build an unsigned version of the iOS app
|
||||
$(call start_packager)
|
||||
@cd fastlane && NODE_ENV=production bundle exec fastlane ios unsigned
|
||||
$(call stop_packager)
|
||||
|
||||
ios-sim-x86_64: stop pre-build check-style ## Build an unsigned x86_64 version of the iOS app for iPhone simulator
|
||||
$(call start_packager)
|
||||
@echo "Building unsigned x86_64 iOS app for iPhone simulator"
|
||||
@cd fastlane && NODE_ENV=production bundle exec fastlane ios simulator
|
||||
$(call stop_packager)
|
||||
|
||||
unsigned-android: stop pre-build check-style prepare-android-build ## Build an unsigned version of the Android app
|
||||
@cd fastlane && NODE_ENV=production bundle exec fastlane android unsigned
|
||||
|
||||
test: | pre-run check-style ## Runs tests
|
||||
@npm test
|
||||
|
||||
build-pr: | can-build-pr stop pre-build check-style ## Build a PR from the mattermost-mobile repo
|
||||
$(call start_packager)
|
||||
@echo "Building App from PR ${PR_ID}"
|
||||
@cd fastlane && BABEL_ENV=production NODE_ENV=production bundle exec fastlane build_pr pr:PR-${PR_ID}
|
||||
$(call stop_packager)
|
||||
|
||||
can-build-pr:
|
||||
@if [ -z ${PR_ID} ]; then \
|
||||
echo a PR number needs to be specified; \
|
||||
exit 1; \
|
||||
fi
|
||||
|
||||
## Help documentation https://marmelab.com/blog/2016/02/29/auto-documented-makefile.html
|
||||
help:
|
||||
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
|
||||
|
||||
define start_packager
|
||||
@if [ $(shell ps -ef | grep -i "cli.js start" | grep -civ grep) -eq 0 ]; then \
|
||||
echo Starting React Native packager server; \
|
||||
npm start & echo; \
|
||||
else \
|
||||
echo React Native packager server already running; \
|
||||
fi
|
||||
endef
|
||||
|
||||
define stop_packager
|
||||
@echo Stopping React Native packager server
|
||||
@if [ $(shell ps -ef | grep -i "cli.js start" | grep -civ grep) -eq 1 ]; then \
|
||||
ps -ef | grep -i "cli.js start" | grep -iv grep | awk '{print $$2}' | xargs kill -9; \
|
||||
echo React Native packager server stopped; \
|
||||
else \
|
||||
echo No React Native packager server running; \
|
||||
fi
|
||||
endef
|
||||
|
|
@ -101,7 +101,7 @@ if (System.getenv("SENTRY_ENABLED") == "true") {
|
|||
* Upload all the APKs to the Play Store and people will download
|
||||
* the correct one based on the CPU architecture of their device.
|
||||
*/
|
||||
def enableSeparateBuildPerCPUArchitecture = false
|
||||
def enableSeparateBuildPerCPUArchitecture = project.hasProperty('separateApk') ? project.property('separateApk').toBoolean() : false
|
||||
|
||||
/**
|
||||
* Run Proguard to shrink the Java bytecode in release builds.
|
||||
|
|
@ -135,9 +135,6 @@ android {
|
|||
versionCode 330
|
||||
versionName "1.36.0"
|
||||
multiDexEnabled = true
|
||||
ndk {
|
||||
abiFilters 'armeabi-v7a','arm64-v8a','x86','x86_64'
|
||||
}
|
||||
testBuildType System.getProperty('testBuildType', 'debug')
|
||||
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
|
||||
}
|
||||
|
|
@ -155,7 +152,7 @@ android {
|
|||
abi {
|
||||
reset()
|
||||
enable enableSeparateBuildPerCPUArchitecture
|
||||
universalApk false // If true, also generate a universal APK
|
||||
universalApk enableSeparateBuildPerCPUArchitecture // If true, also generate a universal APK
|
||||
include "armeabi-v7a", "x86", "arm64-v8a", "x86_64"
|
||||
}
|
||||
}
|
||||
|
|
@ -184,7 +181,7 @@ android {
|
|||
def abi = output.getFilter(OutputFile.ABI)
|
||||
if (abi != null) { // null for the universal-debug, universal-release variants
|
||||
output.versionCodeOverride =
|
||||
versionCodes.get(abi) * 1048576 + defaultConfig.versionCode
|
||||
versionCodes.get(abi) * 1000000 + defaultConfig.versionCode
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,8 +51,7 @@ exports[`AnnouncementBanner should match snapshot 1`] = `
|
|||
value="Banner Text"
|
||||
/>
|
||||
</Text>
|
||||
<Icon
|
||||
allowFontScaling={false}
|
||||
<CompassIcon
|
||||
color="#fff"
|
||||
name="info-outline"
|
||||
size={16}
|
||||
|
|
@ -112,8 +111,7 @@ exports[`AnnouncementBanner should match snapshot 2`] = `
|
|||
value="Banner Text"
|
||||
/>
|
||||
</Text>
|
||||
<Icon
|
||||
allowFontScaling={false}
|
||||
<CompassIcon
|
||||
color="#fff"
|
||||
name="info-outline"
|
||||
size={16}
|
||||
|
|
|
|||
38
app/components/app_version.tsx
Normal file
38
app/components/app_version.tsx
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import React from 'react';
|
||||
import {StyleSheet, View} from 'react-native';
|
||||
import DeviceInfo from 'react-native-device-info';
|
||||
|
||||
import FormattedText from '@components/formatted_text';
|
||||
|
||||
const style = StyleSheet.create({
|
||||
info: {
|
||||
alignItems: 'center',
|
||||
justifyContent: 'flex-end',
|
||||
},
|
||||
version: {
|
||||
fontSize: 12,
|
||||
},
|
||||
});
|
||||
|
||||
const AppVersion = () => {
|
||||
return (
|
||||
<View pointerEvents='none'>
|
||||
<View style={style.info}>
|
||||
<FormattedText
|
||||
id='mobile.about.appVersion'
|
||||
defaultMessage='App Version: {version} (Build {number})'
|
||||
style={style.version}
|
||||
values={{
|
||||
version: DeviceInfo.getVersion(),
|
||||
number: DeviceInfo.getBuildNumber(),
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
export default AppVersion;
|
||||
|
|
@ -13,8 +13,7 @@ exports[`AttachmentButton should match snapshot 1`] = `
|
|||
}
|
||||
type="opacity"
|
||||
>
|
||||
<Icon
|
||||
allowFontScaling={false}
|
||||
<CompassIcon
|
||||
color="rgba(61,60,64,0.9)"
|
||||
name="plus"
|
||||
size={30}
|
||||
|
|
|
|||
|
|
@ -10008,8 +10008,7 @@ exports[`components/emoji_picker/emoji_picker.ios should match snapshot 1`] = `
|
|||
}
|
||||
}
|
||||
>
|
||||
<Icon
|
||||
allowFontScaling={false}
|
||||
<CompassIcon
|
||||
name="emoticon-happy-outline"
|
||||
size={17}
|
||||
style={
|
||||
|
|
@ -10035,8 +10034,7 @@ exports[`components/emoji_picker/emoji_picker.ios should match snapshot 1`] = `
|
|||
}
|
||||
}
|
||||
>
|
||||
<Icon
|
||||
allowFontScaling={false}
|
||||
<CompassIcon
|
||||
name="leaf-outline"
|
||||
size={17}
|
||||
style={
|
||||
|
|
@ -10060,8 +10058,7 @@ exports[`components/emoji_picker/emoji_picker.ios should match snapshot 1`] = `
|
|||
}
|
||||
}
|
||||
>
|
||||
<Icon
|
||||
allowFontScaling={false}
|
||||
<CompassIcon
|
||||
name="food-apple"
|
||||
size={17}
|
||||
style={
|
||||
|
|
@ -10085,8 +10082,7 @@ exports[`components/emoji_picker/emoji_picker.ios should match snapshot 1`] = `
|
|||
}
|
||||
}
|
||||
>
|
||||
<Icon
|
||||
allowFontScaling={false}
|
||||
<CompassIcon
|
||||
name="basketball"
|
||||
size={17}
|
||||
style={
|
||||
|
|
@ -10110,8 +10106,7 @@ exports[`components/emoji_picker/emoji_picker.ios should match snapshot 1`] = `
|
|||
}
|
||||
}
|
||||
>
|
||||
<Icon
|
||||
allowFontScaling={false}
|
||||
<CompassIcon
|
||||
name="airplane-variant"
|
||||
size={17}
|
||||
style={
|
||||
|
|
@ -10135,8 +10130,7 @@ exports[`components/emoji_picker/emoji_picker.ios should match snapshot 1`] = `
|
|||
}
|
||||
}
|
||||
>
|
||||
<Icon
|
||||
allowFontScaling={false}
|
||||
<CompassIcon
|
||||
name="lightbulb-outline"
|
||||
size={17}
|
||||
style={
|
||||
|
|
@ -10160,8 +10154,7 @@ exports[`components/emoji_picker/emoji_picker.ios should match snapshot 1`] = `
|
|||
}
|
||||
}
|
||||
>
|
||||
<Icon
|
||||
allowFontScaling={false}
|
||||
<CompassIcon
|
||||
name="heart-outline"
|
||||
size={17}
|
||||
style={
|
||||
|
|
@ -10185,8 +10178,7 @@ exports[`components/emoji_picker/emoji_picker.ios should match snapshot 1`] = `
|
|||
}
|
||||
}
|
||||
>
|
||||
<Icon
|
||||
allowFontScaling={false}
|
||||
<CompassIcon
|
||||
name="flag-outline"
|
||||
size={17}
|
||||
style={
|
||||
|
|
@ -10210,8 +10202,7 @@ exports[`components/emoji_picker/emoji_picker.ios should match snapshot 1`] = `
|
|||
}
|
||||
}
|
||||
>
|
||||
<Icon
|
||||
allowFontScaling={false}
|
||||
<CompassIcon
|
||||
name="emoticon-custom-outline"
|
||||
size={17}
|
||||
style={
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@ import {shallowWithIntl} from 'test/intl-test-helper';
|
|||
import {filterEmojiSearchInput} from './emoji_picker_base';
|
||||
import EmojiPicker from './emoji_picker.ios';
|
||||
|
||||
jest.useFakeTimers();
|
||||
|
||||
describe('components/emoji_picker/emoji_picker.ios', () => {
|
||||
const state = {
|
||||
...initialState,
|
||||
|
|
@ -59,17 +61,17 @@ describe('components/emoji_picker/emoji_picker.ios', () => {
|
|||
];
|
||||
|
||||
testCases.forEach((testCase) => {
|
||||
test(`'${testCase.input}' should return '${testCase.output}'`, () => {
|
||||
test(`'${testCase.input}' should return '${testCase.output}'`, async () => {
|
||||
expect(filterEmojiSearchInput(testCase.input)).toEqual(testCase.output);
|
||||
});
|
||||
});
|
||||
|
||||
test('should match snapshot', () => {
|
||||
test('should match snapshot', async () => {
|
||||
const wrapper = shallowWithIntl(<EmojiPicker {...baseProps}/>);
|
||||
expect(wrapper.getElement()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('searchEmojis should return the right values on fuse', () => {
|
||||
test('searchEmojis should return the right values on fuse', async () => {
|
||||
const input = '1';
|
||||
const output = ['100', '1234', '1st_place_medal', '+1', '-1', 'u7121'];
|
||||
|
||||
|
|
@ -78,7 +80,7 @@ describe('components/emoji_picker/emoji_picker.ios', () => {
|
|||
expect(result).toEqual(output);
|
||||
});
|
||||
|
||||
test('should set rebuildEmojis to true when deviceWidth changes', () => {
|
||||
test('should set rebuildEmojis to true when deviceWidth changes', async () => {
|
||||
const wrapper = shallowWithIntl(<EmojiPicker {...baseProps}/>);
|
||||
const instance = wrapper.instance();
|
||||
|
||||
|
|
@ -90,7 +92,7 @@ describe('components/emoji_picker/emoji_picker.ios', () => {
|
|||
expect(instance.rebuildEmojis).toBe(true);
|
||||
});
|
||||
|
||||
test('should rebuild emojis emojis when emojis change', () => {
|
||||
test('should rebuild emojis emojis when emojis change', async () => {
|
||||
const wrapper = shallowWithIntl(<EmojiPicker {...baseProps}/>);
|
||||
const instance = wrapper.instance();
|
||||
const renderableEmojis = jest.spyOn(instance, 'renderableEmojis');
|
||||
|
|
@ -103,7 +105,7 @@ describe('components/emoji_picker/emoji_picker.ios', () => {
|
|||
expect(renderableEmojis).toHaveBeenCalledWith(baseProps.emojisBySection, baseProps.deviceWidth);
|
||||
});
|
||||
|
||||
test('should set rebuilt emojis when rebuildEmojis is true and searchBarAnimationComplete is true', () => {
|
||||
test('should set rebuilt emojis when rebuildEmojis is true and searchBarAnimationComplete is true', async () => {
|
||||
const wrapper = shallowWithIntl(<EmojiPicker {...baseProps}/>);
|
||||
const instance = wrapper.instance();
|
||||
instance.setState = jest.fn();
|
||||
|
|
@ -118,7 +120,7 @@ describe('components/emoji_picker/emoji_picker.ios', () => {
|
|||
expect(instance.rebuildEmojis).toBe(false);
|
||||
});
|
||||
|
||||
test('should not set rebuilt emojis when rebuildEmojis is false and searchBarAnimationComplete is true', () => {
|
||||
test('should not set rebuilt emojis when rebuildEmojis is false and searchBarAnimationComplete is true', async () => {
|
||||
const wrapper = shallowWithIntl(<EmojiPicker {...baseProps}/>);
|
||||
const instance = wrapper.instance();
|
||||
instance.setState = jest.fn();
|
||||
|
|
@ -131,7 +133,7 @@ describe('components/emoji_picker/emoji_picker.ios', () => {
|
|||
expect(instance.setState).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('should not set rebuilt emojis when rebuildEmojis is true and searchBarAnimationComplete is false', () => {
|
||||
test('should not set rebuilt emojis when rebuildEmojis is true and searchBarAnimationComplete is false', async () => {
|
||||
const wrapper = shallowWithIntl(<EmojiPicker {...baseProps}/>);
|
||||
const instance = wrapper.instance();
|
||||
instance.setState = jest.fn();
|
||||
|
|
|
|||
|
|
@ -7,9 +7,6 @@ import {shallow} from 'enzyme';
|
|||
import InteractiveDialogController from './interactive_dialog_controller';
|
||||
|
||||
jest.mock('react-intl');
|
||||
jest.mock('react-native-vector-icons/MaterialIcons', () => ({
|
||||
getImageSource: jest.fn().mockResolvedValue({}),
|
||||
}));
|
||||
|
||||
describe('InteractiveDialogController', () => {
|
||||
test('should open interactive dialog as alert or screen depending on with or without element', () => {
|
||||
|
|
|
|||
|
|
@ -54,8 +54,7 @@ exports[`AttachmentFooter matches snapshot 1`] = `
|
|||
}
|
||||
}
|
||||
>
|
||||
<Icon
|
||||
allowFontScaling={false}
|
||||
<CompassIcon
|
||||
color="#FFFFFF"
|
||||
name="check"
|
||||
size={20}
|
||||
|
|
|
|||
|
|
@ -12,8 +12,7 @@ exports[`CameraButton should match snapshot 1`] = `
|
|||
}
|
||||
type="opacity"
|
||||
>
|
||||
<Icon
|
||||
allowFontScaling={false}
|
||||
<CompassIcon
|
||||
color="rgba(61,60,64,0.64)"
|
||||
name="camera-outline"
|
||||
size={24}
|
||||
|
|
|
|||
|
|
@ -12,8 +12,7 @@ exports[`FileQuickAction should match snapshot 1`] = `
|
|||
}
|
||||
type="opacity"
|
||||
>
|
||||
<Icon
|
||||
allowFontScaling={false}
|
||||
<CompassIcon
|
||||
color="rgba(61,60,64,0.64)"
|
||||
name="file-document-outline"
|
||||
size={24}
|
||||
|
|
|
|||
|
|
@ -12,8 +12,7 @@ exports[`ImageQuickAction should match snapshot 1`] = `
|
|||
}
|
||||
type="opacity"
|
||||
>
|
||||
<Icon
|
||||
allowFontScaling={false}
|
||||
<CompassIcon
|
||||
color="rgba(61,60,64,0.64)"
|
||||
name="image-outline"
|
||||
size={24}
|
||||
|
|
|
|||
|
|
@ -20,11 +20,9 @@ exports[`PostDraft ReadOnly Should match snapshot 1`] = `
|
|||
}
|
||||
}
|
||||
>
|
||||
<Icon
|
||||
allowFontScaling={false}
|
||||
<CompassIcon
|
||||
color="#3d3c40"
|
||||
name="glasses"
|
||||
size={12}
|
||||
style={
|
||||
Object {
|
||||
"fontSize": 20,
|
||||
|
|
|
|||
|
|
@ -27,8 +27,7 @@ exports[`SendAction should change theme backgroundColor to 0.3 opacity 1`] = `
|
|||
]
|
||||
}
|
||||
>
|
||||
<Icon
|
||||
allowFontScaling={false}
|
||||
<CompassIcon
|
||||
color="rgba(255,255,255,0.5)"
|
||||
name="send"
|
||||
size={24}
|
||||
|
|
@ -61,8 +60,7 @@ exports[`SendAction should match snapshot 1`] = `
|
|||
}
|
||||
}
|
||||
>
|
||||
<Icon
|
||||
allowFontScaling={false}
|
||||
<CompassIcon
|
||||
color="#ffffff"
|
||||
name="send"
|
||||
size={24}
|
||||
|
|
@ -95,8 +93,7 @@ exports[`SendAction should render theme backgroundColor 1`] = `
|
|||
}
|
||||
}
|
||||
>
|
||||
<Icon
|
||||
allowFontScaling={false}
|
||||
<CompassIcon
|
||||
color="#ffffff"
|
||||
name="send"
|
||||
size={24}
|
||||
|
|
|
|||
|
|
@ -531,8 +531,7 @@ exports[`PostHeader should match snapshot when post isBot and shouldRenderReplyB
|
|||
}
|
||||
type="opacity"
|
||||
>
|
||||
<Icon
|
||||
allowFontScaling={false}
|
||||
<CompassIcon
|
||||
color="#2389d7"
|
||||
name="reply-outline"
|
||||
size={18}
|
||||
|
|
@ -684,8 +683,7 @@ exports[`PostHeader should match snapshot when post isBot and shouldRenderReplyB
|
|||
}
|
||||
type="opacity"
|
||||
>
|
||||
<Icon
|
||||
allowFontScaling={false}
|
||||
<CompassIcon
|
||||
color="#2389d7"
|
||||
name="reply-outline"
|
||||
size={18}
|
||||
|
|
@ -884,8 +882,7 @@ exports[`PostHeader should match snapshot when post should display reply button
|
|||
}
|
||||
type="opacity"
|
||||
>
|
||||
<Icon
|
||||
allowFontScaling={false}
|
||||
<CompassIcon
|
||||
color="#2389d7"
|
||||
name="reply-outline"
|
||||
size={18}
|
||||
|
|
|
|||
|
|
@ -27,8 +27,7 @@ exports[`PostPreHeader should match snapshot when flagged and not pinned 1`] = `
|
|||
}
|
||||
}
|
||||
>
|
||||
<Icon
|
||||
allowFontScaling={false}
|
||||
<CompassIcon
|
||||
name="bookmark-outline"
|
||||
size={14}
|
||||
style={
|
||||
|
|
@ -91,8 +90,7 @@ exports[`PostPreHeader should match snapshot when pinned and flagged 1`] = `
|
|||
}
|
||||
}
|
||||
>
|
||||
<Icon
|
||||
allowFontScaling={false}
|
||||
<CompassIcon
|
||||
name="pin-outline"
|
||||
size={14}
|
||||
style={
|
||||
|
|
@ -108,8 +106,7 @@ exports[`PostPreHeader should match snapshot when pinned and flagged 1`] = `
|
|||
}
|
||||
}
|
||||
/>
|
||||
<Icon
|
||||
allowFontScaling={false}
|
||||
<CompassIcon
|
||||
name="bookmark-outline"
|
||||
size={14}
|
||||
style={
|
||||
|
|
@ -170,8 +167,7 @@ exports[`PostPreHeader should match snapshot when pinned and flagged but skippin
|
|||
}
|
||||
}
|
||||
>
|
||||
<Icon
|
||||
allowFontScaling={false}
|
||||
<CompassIcon
|
||||
name="pin-outline"
|
||||
size={14}
|
||||
style={
|
||||
|
|
@ -230,8 +226,7 @@ exports[`PostPreHeader should match snapshot when pinned and flagged but skippin
|
|||
}
|
||||
}
|
||||
>
|
||||
<Icon
|
||||
allowFontScaling={false}
|
||||
<CompassIcon
|
||||
name="bookmark-outline"
|
||||
size={14}
|
||||
style={
|
||||
|
|
@ -290,8 +285,7 @@ exports[`PostPreHeader should match snapshot when pinned and not flagged 1`] = `
|
|||
}
|
||||
}
|
||||
>
|
||||
<Icon
|
||||
allowFontScaling={false}
|
||||
<CompassIcon
|
||||
name="pin-outline"
|
||||
size={14}
|
||||
style={
|
||||
|
|
|
|||
|
|
@ -69,10 +69,8 @@ exports[`MoreMessagesButton should match snapshot 1`] = `
|
|||
}
|
||||
}
|
||||
>
|
||||
<Icon
|
||||
allowFontScaling={false}
|
||||
<CompassIcon
|
||||
name="arrow-up"
|
||||
size={12}
|
||||
style={
|
||||
Object {
|
||||
"alignSelf": "center",
|
||||
|
|
@ -118,10 +116,8 @@ exports[`MoreMessagesButton should match snapshot 1`] = `
|
|||
}
|
||||
}
|
||||
>
|
||||
<Icon
|
||||
allowFontScaling={false}
|
||||
<CompassIcon
|
||||
name="close"
|
||||
size={12}
|
||||
style={
|
||||
Object {
|
||||
"alignSelf": "center",
|
||||
|
|
|
|||
|
|
@ -247,8 +247,7 @@ exports[`Reactions Should match snapshot with default emojis 1`] = `
|
|||
]
|
||||
}
|
||||
>
|
||||
<Icon
|
||||
allowFontScaling={false}
|
||||
<CompassIcon
|
||||
name="emoticon-plus-outline"
|
||||
size={31.2}
|
||||
style={
|
||||
|
|
@ -509,8 +508,7 @@ exports[`Reactions Should match snapshot with default emojis 2`] = `
|
|||
]
|
||||
}
|
||||
>
|
||||
<Icon
|
||||
allowFontScaling={false}
|
||||
<CompassIcon
|
||||
name="emoticon-plus-outline"
|
||||
size={31.2}
|
||||
style={
|
||||
|
|
|
|||
|
|
@ -145,8 +145,7 @@ exports[`Reactions should match snapshot 1`] = `
|
|||
}
|
||||
type="opacity"
|
||||
>
|
||||
<Icon
|
||||
allowFontScaling={false}
|
||||
<CompassIcon
|
||||
name="emoticon-plus-outline"
|
||||
size={24}
|
||||
style={
|
||||
|
|
|
|||
|
|
@ -4,8 +4,7 @@ exports[`ShowMoreButton should match, button snapshot 1`] = `
|
|||
<View
|
||||
style={Object {}}
|
||||
>
|
||||
<Icon
|
||||
allowFontScaling={false}
|
||||
<CompassIcon
|
||||
name="plus"
|
||||
size={18}
|
||||
style={Object {}}
|
||||
|
|
@ -22,8 +21,7 @@ exports[`ShowMoreButton should match, button snapshot 2`] = `
|
|||
<View
|
||||
style={Object {}}
|
||||
>
|
||||
<Icon
|
||||
allowFontScaling={false}
|
||||
<CompassIcon
|
||||
name="minus"
|
||||
size={18}
|
||||
style={Object {}}
|
||||
|
|
@ -121,8 +119,7 @@ exports[`ShowMoreButton should match, full snapshot 1`] = `
|
|||
}
|
||||
}
|
||||
>
|
||||
<Icon
|
||||
allowFontScaling={false}
|
||||
<CompassIcon
|
||||
name="plus"
|
||||
size={18}
|
||||
style={
|
||||
|
|
|
|||
|
|
@ -1,10 +1,8 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`UserStatus should match snapshot, away status 1`] = `
|
||||
<Icon
|
||||
allowFontScaling={false}
|
||||
<CompassIcon
|
||||
name="clock"
|
||||
size={12}
|
||||
style={
|
||||
Object {
|
||||
"color": "#ffbc42",
|
||||
|
|
@ -15,10 +13,8 @@ exports[`UserStatus should match snapshot, away status 1`] = `
|
|||
`;
|
||||
|
||||
exports[`UserStatus should match snapshot, dnd status 1`] = `
|
||||
<Icon
|
||||
allowFontScaling={false}
|
||||
<CompassIcon
|
||||
name="minus-circle"
|
||||
size={12}
|
||||
style={
|
||||
Object {
|
||||
"color": "#f74343",
|
||||
|
|
@ -29,10 +25,8 @@ exports[`UserStatus should match snapshot, dnd status 1`] = `
|
|||
`;
|
||||
|
||||
exports[`UserStatus should match snapshot, online status 1`] = `
|
||||
<Icon
|
||||
allowFontScaling={false}
|
||||
<CompassIcon
|
||||
name="check-circle"
|
||||
size={12}
|
||||
style={
|
||||
Object {
|
||||
"color": "#06d6a0",
|
||||
|
|
@ -43,10 +37,8 @@ exports[`UserStatus should match snapshot, online status 1`] = `
|
|||
`;
|
||||
|
||||
exports[`UserStatus should match snapshot, should default to offline status 1`] = `
|
||||
<Icon
|
||||
allowFontScaling={false}
|
||||
<CompassIcon
|
||||
name="circle-outline"
|
||||
size={12}
|
||||
style={
|
||||
Object {
|
||||
"color": "rgba(61,60,64,0.3)",
|
||||
|
|
|
|||
|
|
@ -158,10 +158,8 @@ exports[`components/widgets/settings/RadioSetting should match snapshot when err
|
|||
this is administration
|
||||
</Text>
|
||||
</View>
|
||||
<Icon
|
||||
allowFontScaling={false}
|
||||
<CompassIcon
|
||||
name="check"
|
||||
size={12}
|
||||
style={
|
||||
Object {
|
||||
"color": "#2389d7",
|
||||
|
|
|
|||
|
|
@ -16,9 +16,6 @@ import {emptyFunction} from '@utils/general';
|
|||
import ChannelBase from './channel_base';
|
||||
|
||||
jest.mock('react-intl');
|
||||
jest.mock('react-native-vector-icons/MaterialIcons', () => ({
|
||||
getImageSource: jest.fn().mockResolvedValue(null),
|
||||
}));
|
||||
|
||||
describe('ChannelBase', () => {
|
||||
const channelBaseComponentId = 'component-0';
|
||||
|
|
|
|||
|
|
@ -24,8 +24,7 @@ exports[`SettingDrawerButton should match, full snapshot 1`] = `
|
|||
}
|
||||
}
|
||||
>
|
||||
<Icon
|
||||
allowFontScaling={false}
|
||||
<CompassIcon
|
||||
color="#ffffff"
|
||||
name="dots-vertical"
|
||||
size={25}
|
||||
|
|
|
|||
|
|
@ -66,8 +66,7 @@ exports[`ChannelDrawerButton should match, full snapshot 2`] = `
|
|||
}
|
||||
>
|
||||
<View>
|
||||
<Icon
|
||||
allowFontScaling={false}
|
||||
<CompassIcon
|
||||
color="#ffffff"
|
||||
name="menu-variant"
|
||||
size={24}
|
||||
|
|
|
|||
|
|
@ -31,8 +31,7 @@ exports[`ChannelSearchButton should match, full snapshot 1`] = `
|
|||
}
|
||||
}
|
||||
>
|
||||
<Icon
|
||||
allowFontScaling={false}
|
||||
<CompassIcon
|
||||
name="magnify"
|
||||
size={24}
|
||||
style={
|
||||
|
|
|
|||
|
|
@ -35,8 +35,7 @@ exports[`ChannelTitle should match snapshot 1`] = `
|
|||
>
|
||||
My Channel
|
||||
</Text>
|
||||
<Icon
|
||||
allowFontScaling={false}
|
||||
<CompassIcon
|
||||
name="chevron-down"
|
||||
size={24}
|
||||
style={
|
||||
|
|
@ -85,8 +84,7 @@ exports[`ChannelTitle should match snapshot when is DM and has guests and the te
|
|||
>
|
||||
Other user
|
||||
</Text>
|
||||
<Icon
|
||||
allowFontScaling={false}
|
||||
<CompassIcon
|
||||
name="chevron-down"
|
||||
size={24}
|
||||
style={
|
||||
|
|
@ -160,8 +158,7 @@ exports[`ChannelTitle should match snapshot when is DM and has guests but the te
|
|||
>
|
||||
Other user
|
||||
</Text>
|
||||
<Icon
|
||||
allowFontScaling={false}
|
||||
<CompassIcon
|
||||
name="chevron-down"
|
||||
size={24}
|
||||
style={
|
||||
|
|
@ -218,8 +215,7 @@ exports[`ChannelTitle should match snapshot when isSelfDMChannel is true 1`] = `
|
|||
}
|
||||
/>
|
||||
</Text>
|
||||
<Icon
|
||||
allowFontScaling={false}
|
||||
<CompassIcon
|
||||
name="chevron-down"
|
||||
size={24}
|
||||
style={
|
||||
|
|
|
|||
|
|
@ -23,8 +23,7 @@ exports[`ForgotPassword match snapshot after success of sendPasswordResetEmail 1
|
|||
}
|
||||
}
|
||||
>
|
||||
<Icon
|
||||
allowFontScaling={false}
|
||||
<CompassIcon
|
||||
name="mattermost"
|
||||
size={76}
|
||||
style={
|
||||
|
|
@ -109,8 +108,7 @@ exports[`ForgotPassword should match snapshot 1`] = `
|
|||
}
|
||||
}
|
||||
>
|
||||
<Icon
|
||||
allowFontScaling={false}
|
||||
<CompassIcon
|
||||
name="mattermost"
|
||||
size={76}
|
||||
style={
|
||||
|
|
@ -223,8 +221,7 @@ exports[`ForgotPassword snapshot for error on failure of email regex 1`] = `
|
|||
}
|
||||
}
|
||||
>
|
||||
<Icon
|
||||
allowFontScaling={false}
|
||||
<CompassIcon
|
||||
name="mattermost"
|
||||
size={76}
|
||||
style={
|
||||
|
|
|
|||
|
|
@ -105,8 +105,7 @@ exports[`ImagePreview should match snapshot 1`] = `
|
|||
}
|
||||
}
|
||||
>
|
||||
<Icon
|
||||
allowFontScaling={false}
|
||||
<CompassIcon
|
||||
color="#fff"
|
||||
name="close"
|
||||
size={24}
|
||||
|
|
@ -136,8 +135,7 @@ exports[`ImagePreview should match snapshot 1`] = `
|
|||
}
|
||||
}
|
||||
>
|
||||
<Icon
|
||||
allowFontScaling={false}
|
||||
<CompassIcon
|
||||
color="#fff"
|
||||
name="download-outline"
|
||||
size={24}
|
||||
|
|
@ -256,8 +254,7 @@ exports[`ImagePreview should match snapshot, renderDownloadButton 1`] = `
|
|||
}
|
||||
}
|
||||
>
|
||||
<Icon
|
||||
allowFontScaling={false}
|
||||
<CompassIcon
|
||||
color="#fff"
|
||||
name="download-outline"
|
||||
size={24}
|
||||
|
|
|
|||
|
|
@ -281,8 +281,7 @@ LongPost {
|
|||
}
|
||||
}
|
||||
>
|
||||
<Icon
|
||||
allowFontScaling={false}
|
||||
<CompassIcon
|
||||
color="#3d3c40"
|
||||
name="close"
|
||||
size={20}
|
||||
|
|
|
|||
|
|
@ -75,10 +75,8 @@ exports[`MoreChannels should match snapshot 1`] = `
|
|||
}
|
||||
>
|
||||
|
||||
<Icon
|
||||
allowFontScaling={false}
|
||||
<CompassIcon
|
||||
name="menu-down"
|
||||
size={12}
|
||||
/>
|
||||
</Text>
|
||||
</View>
|
||||
|
|
|
|||
|
|
@ -54,8 +54,7 @@ exports[`OptionModalList should match snapshot for Android 1`] = `
|
|||
]
|
||||
}
|
||||
/>
|
||||
<Icon
|
||||
allowFontScaling={false}
|
||||
<CompassIcon
|
||||
name="camera"
|
||||
size={18}
|
||||
style={
|
||||
|
|
@ -100,8 +99,7 @@ exports[`OptionModalList should match snapshot for Android 1`] = `
|
|||
]
|
||||
}
|
||||
/>
|
||||
<Icon
|
||||
allowFontScaling={false}
|
||||
<CompassIcon
|
||||
name="photo"
|
||||
size={18}
|
||||
style={
|
||||
|
|
@ -230,8 +228,7 @@ exports[`OptionModalList should match snapshot for iOS 1`] = `
|
|||
]
|
||||
}
|
||||
/>
|
||||
<Icon
|
||||
allowFontScaling={false}
|
||||
<CompassIcon
|
||||
name="camera"
|
||||
size={24}
|
||||
style={
|
||||
|
|
@ -276,8 +273,7 @@ exports[`OptionModalList should match snapshot for iOS 1`] = `
|
|||
]
|
||||
}
|
||||
/>
|
||||
<Icon
|
||||
allowFontScaling={false}
|
||||
<CompassIcon
|
||||
name="photo"
|
||||
size={24}
|
||||
style={
|
||||
|
|
|
|||
|
|
@ -63,8 +63,7 @@ exports[`Permalink should match snapshot 1`] = `
|
|||
}
|
||||
}
|
||||
>
|
||||
<Icon
|
||||
allowFontScaling={false}
|
||||
<CompassIcon
|
||||
color="#3d3c40"
|
||||
name="close"
|
||||
size={20}
|
||||
|
|
@ -133,10 +132,8 @@ exports[`Permalink should match snapshot 1`] = `
|
|||
|
||||
exports[`Permalink should match snapshot 2`] = `
|
||||
<Text>
|
||||
<Icon
|
||||
allowFontScaling={false}
|
||||
<CompassIcon
|
||||
name="archive-outline"
|
||||
size={12}
|
||||
style={
|
||||
Array [
|
||||
Object {
|
||||
|
|
|
|||
|
|
@ -43,8 +43,7 @@ exports[`Search RecentItem should match snapshot and respond to events 1`] = `
|
|||
}
|
||||
}
|
||||
>
|
||||
<Icon
|
||||
allowFontScaling={false}
|
||||
<CompassIcon
|
||||
color="rgba(61,60,64,0.6)"
|
||||
name="close-circle-outline"
|
||||
size={20}
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ import urlParse from 'url-parse';
|
|||
|
||||
import {resetToChannel, goToScreen} from '@actions/navigation';
|
||||
import LocalConfig from '@assets/config';
|
||||
import AppVersion from '@components/app_version';
|
||||
import CompassIcon from '@components/compass_icon';
|
||||
import ErrorText from '@components/error_text';
|
||||
import FormattedText from '@components/formatted_text';
|
||||
|
|
@ -561,6 +562,7 @@ export default class SelectServer extends PureComponent {
|
|||
</View>
|
||||
</View>
|
||||
</TouchableWithoutFeedback>
|
||||
<AppVersion/>
|
||||
</KeyboardAvoidingView>
|
||||
</SafeAreaView>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
fastlane_version '2.71.0'
|
||||
|
||||
fastlane_require 'aws-sdk-s3'
|
||||
fastlane_require 'erb'
|
||||
fastlane_require 'json'
|
||||
|
|
@ -46,10 +45,6 @@ end
|
|||
|
||||
after_all do |lane|
|
||||
if ENV['CIRCLECI'] != 'true'
|
||||
if lane.to_s == 'build'
|
||||
submit_to_store
|
||||
end
|
||||
|
||||
if ENV['RESET_GIT_BRANCH'] == 'true'
|
||||
branch = ENV['BRANCH_TO_BUILD'] || 'master'
|
||||
package_id = ENV['MAIN_APP_IDENTIFIER'] || 'com.mattermost.rnbeta'
|
||||
|
|
@ -174,106 +169,106 @@ lane :configure do
|
|||
configured = true
|
||||
end
|
||||
|
||||
desc 'Build the app for Android and iOS'
|
||||
lane :build do |options|
|
||||
configure
|
||||
set_app_version
|
||||
set_app_build_number
|
||||
|
||||
# Build the android app
|
||||
self.runner.current_platform = :android
|
||||
build
|
||||
|
||||
# Build the ios app
|
||||
self.runner.current_platform = :ios
|
||||
build
|
||||
end
|
||||
|
||||
desc 'Upload file to s3'
|
||||
lane :upload_file_to_s3 do |options|
|
||||
os_type = options[:os_type]
|
||||
file = options[:file]
|
||||
file_plist = ""
|
||||
|
||||
if file.nil? || file.empty?
|
||||
app_name = ENV['APP_NAME'] || 'Mattermost Beta'
|
||||
filename = app_name.gsub(" ", "_")
|
||||
|
||||
if os_type == 'Android'
|
||||
file = "#{filename}.apk"
|
||||
elsif os_type == 'iOS'
|
||||
file = "#{filename}.ipa"
|
||||
file_plist = "#{filename}.plist"
|
||||
end
|
||||
os_type = options[:os_type].downcase
|
||||
extension = os_type == "android" ? "*.apk" : "*.ipa"
|
||||
build_folder_path = Dir[File.expand_path('..')].first
|
||||
files = []
|
||||
|
||||
unless options[:file].nil? || options[:file].empty?
|
||||
files.push("#{build_folder_path}/#{options[:file]}")
|
||||
else
|
||||
files = Dir.glob("#{build_folder_path}/#{extension}").select { |f| File.file? f}
|
||||
end
|
||||
|
||||
build_folder_path = Dir[File.expand_path('..')].first
|
||||
file_path = "#{build_folder_path}/#{file}"
|
||||
|
||||
unless ENV['AWS_BUCKET_NAME'].nil? || ENV['AWS_BUCKET_NAME'].empty? || ENV['AWS_REGION'].nil? || ENV['AWS_REGION'].empty? || file_path.nil?
|
||||
s3_region = ENV['AWS_REGION']
|
||||
s3_bucket = ENV['AWS_BUCKET_NAME']
|
||||
s3_folder = ''
|
||||
|
||||
unless ENV['AWS_BUCKET_NAME'].nil? || ENV['AWS_BUCKET_NAME'].empty? || ENV['AWS_REGION'].nil? || ENV['AWS_REGION'].empty? || files.length == 0
|
||||
version_number = ''
|
||||
build_number = ''
|
||||
pr_file = ''
|
||||
plist_file = ''
|
||||
|
||||
if is_build_pr
|
||||
s3_folder = "#{ENV['AWS_FOLDER_NAME']}/#{ENV['BRANCH_TO_BUILD']}"
|
||||
pr_file = File.basename(files.first)
|
||||
plist_file = "#{File.basename(files.first, '.*')}.plist"
|
||||
else
|
||||
if os_type == 'Android'
|
||||
version_number = android_get_version_name(gradle_file: './android/app/build.gradle')
|
||||
build_number = android_get_version_code(gradle_file: './android/app/build.gradle')
|
||||
elsif os_type == 'iOS'
|
||||
version_number = get_version_number(xcodeproj: './ios/Mattermost.xcodeproj', target: 'Mattermost')
|
||||
build_number = get_build_number(xcodeproj: './ios/Mattermost.xcodeproj')
|
||||
end
|
||||
|
||||
s3_folder = "#{ENV['AWS_FOLDER_NAME']}/#{version_number}/#{build_number}"
|
||||
version_number = os_type == "android" ?
|
||||
android_get_version_name(gradle_file: './android/app/build.gradle') :
|
||||
get_version_number(xcodeproj: './ios/Mattermost.xcodeproj', target: 'Mattermost')
|
||||
build_number = os_type == "android" ?
|
||||
android_get_version_code(gradle_file: './android/app/build.gradle') :
|
||||
get_build_number(xcodeproj: './ios/Mattermost.xcodeproj')
|
||||
end
|
||||
|
||||
s3_region = ENV['AWS_REGION']
|
||||
s3_bucket_name = ENV['AWS_BUCKET_NAME']
|
||||
s3_folder = is_build_pr ?
|
||||
"#{ENV['AWS_FOLDER_NAME']}/#{ENV['BRANCH_TO_BUILD']}" :
|
||||
"#{ENV['AWS_FOLDER_NAME']}/#{version_number}/#{build_number}"
|
||||
|
||||
s3 = Aws::S3::Resource.new(region: s3_region)
|
||||
file_obj = s3.bucket(s3_bucket).object("#{s3_folder}/#{file}")
|
||||
file_obj.upload_file("#{file_path}")
|
||||
s3_bucket = s3.bucket(s3_bucket_name)
|
||||
mutex = Mutex.new
|
||||
threads = []
|
||||
file_number = 0
|
||||
total_files = files.length
|
||||
links = []
|
||||
total_files.times do |i|
|
||||
threads[i] = Thread.new {
|
||||
until files.empty?
|
||||
mutex.synchronize do
|
||||
file_number += 1
|
||||
Thread.current["file_number"] = file_number
|
||||
end
|
||||
file = files.pop rescue nil
|
||||
next unless file
|
||||
|
||||
filename = File.basename(file)
|
||||
puts "[#{Thread.current["file_number"]}/#{total_files}] #{filename} uploading..."
|
||||
s3_file = s3_bucket.object("#{s3_folder}/#{filename}")
|
||||
s3_file.upload_file("#{file}")
|
||||
links.push(s3_file.public_url)
|
||||
end
|
||||
}
|
||||
end
|
||||
threads.each { |t| t.join }
|
||||
|
||||
if is_build_pr
|
||||
if os_type == 'Android'
|
||||
install_url = "https://#{s3_bucket}/#{s3_folder}/#{file}"
|
||||
install_url = "https://#{s3_bucket_name}/#{s3_folder}/#{pr_file}"
|
||||
elsif os_type == 'iOS'
|
||||
current_build_number = get_build_number(xcodeproj: './ios/Mattermost.xcodeproj')
|
||||
plist_template = File.read('plist.erb')
|
||||
plist_body = ERB.new(plist_template).result(binding)
|
||||
|
||||
plist_obj = s3.bucket(s3_bucket).object("#{s3_folder}/#{file_plist}")
|
||||
plist_obj = s3_bucket.object("#{s3_folder}/#{file_plist}")
|
||||
plist_obj.put(body: plist_body)
|
||||
|
||||
install_url = "itms-services://?action=download-manifest&url=https://#{s3_bucket}/#{s3_folder}/#{file_plist}"
|
||||
install_url = "itms-services://?action=download-manifest&url=https://#{s3_bucket_name}/#{s3_folder}/#{file_plist}"
|
||||
end
|
||||
|
||||
qa_build_message({
|
||||
:os_type => os_type,
|
||||
:install_url => install_url
|
||||
})
|
||||
:os_type => os_type,
|
||||
:install_url => install_url
|
||||
})
|
||||
end
|
||||
|
||||
public_link = "https://#{s3_bucket}/#{s3_folder}/#{file}"
|
||||
if file == 'Mattermost-simulator-x86_64.app.zip'
|
||||
|
||||
if options[:file] == 'Mattermost-simulator-x86_64.app.zip'
|
||||
pretext = '#### New iOS build for VM/Simulator'
|
||||
msg = "Download link: #{public_link}"
|
||||
msg = "Download link: #{links.first}"
|
||||
send_message_to_mattermost({
|
||||
:version_number => version_number,
|
||||
:build_number => build_number,
|
||||
:pretext => pretext,
|
||||
:title => '',
|
||||
:thumb_url => 'https://support.apple.com/library/content/dam/edam/applecare/images/en_US/iOS/move-to-ios-icon.png',
|
||||
:msg => msg,
|
||||
:default_payloads => [],
|
||||
:success => true,
|
||||
})
|
||||
:version_number => version_number,
|
||||
:build_number => build_number,
|
||||
:pretext => pretext,
|
||||
:title => '',
|
||||
:thumb_url => 'https://support.apple.com/library/content/dam/edam/applecare/images/en_US/iOS/move-to-ios-icon.png',
|
||||
:msg => msg,
|
||||
:default_payloads => [],
|
||||
:success => true,
|
||||
})
|
||||
end
|
||||
|
||||
UI.success("S3 bucket @#{s3_bucket}, object @#{s3_folder}/#{file}")
|
||||
UI.success("S3 public path: #{public_link}")
|
||||
UI.message("S3 public paths:\n#{links.join("\n")}")
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -285,8 +280,15 @@ lane :github do
|
|||
version = android_get_version_name(gradle_file: './android/app/build.gradle')
|
||||
build = android_get_version_code(gradle_file: './android/app/build.gradle')
|
||||
changelog = File.read("metadata/changelog")
|
||||
changelog.concat("* Android [Mattermost.apk](https://releases.mattermost.com/mattermost-mobile/#{version}/#{build}/Mattermost.apk)\n")
|
||||
changelog.concat("* iOS [Mattermost.ipa](https://releases.mattermost.com/mattermost-mobile/#{version}/#{build}/Mattermost.ipa)")
|
||||
android = [
|
||||
" * [Mattermost arm64-v8a](https://releases.mattermost.com/mattermost-mobile/#{version}/#{build}/Mattermost-arm64-v8a.apk)",
|
||||
" * [Mattermost armeabi-v7a](https://releases.mattermost.com/mattermost-mobile/#{version}/#{build}/Mattermost-armeabi-v7a.apk)",
|
||||
" * [Mattermost Universal](https://releases.mattermost.com/mattermost-mobile/#{version}/#{build}/Mattermost-universal.apk)",
|
||||
" * [Mattermost x86](https://releases.mattermost.com/mattermost-mobile/#{version}/#{build}/Mattermost-x86.apk)",
|
||||
" * [Mattermost x86_64](https://releases.mattermost.com/mattermost-mobile/#{version}/#{build}/Mattermost-x86_64.apk)",
|
||||
]
|
||||
changelog.concat("* Android\n#{android.join("\n")}\n")
|
||||
changelog.concat("* iOS\n * [Mattermost](https://releases.mattermost.com/mattermost-mobile/#{version}/#{build}/Mattermost.ipa)")
|
||||
|
||||
github_release = set_github_release(
|
||||
repository_name: "mattermost/mattermost-mobile",
|
||||
|
|
@ -334,12 +336,12 @@ platform :ios do
|
|||
ENV['APP_NAME'] = 'Mattermost'
|
||||
ENV['REPLACE_ASSETS'] = 'true'
|
||||
ENV['BUILD_FOR_RELEASE'] = 'true'
|
||||
ENV['APP_SCHEME'] = 'mattermost-mobile'
|
||||
ENV['APP_SCHEME'] = 'mattermost'
|
||||
|
||||
update_identifiers
|
||||
replace_assets
|
||||
|
||||
sh 'mkdir -p ../build-ios'
|
||||
sh 'rm -rf ../build-ios/'
|
||||
sh 'cd ../ios/ && xcodebuild -workspace Mattermost.xcworkspace/ -scheme Mattermost -sdk iphoneos -configuration Release -parallelizeTargets -resultBundlePath ../build-ios/result -derivedDataPath ../build-ios/ CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO'
|
||||
sh 'cd ../build-ios/ && mkdir -p Payload && cp -R Build/Products/Release-iphoneos/Mattermost.app Payload/ && zip -r Mattermost-unsigned.ipa Payload/'
|
||||
sh 'mv ../build-ios/Mattermost-unsigned.ipa ../'
|
||||
|
|
@ -352,20 +354,17 @@ platform :ios do
|
|||
ENV['APP_NAME'] = 'Mattermost'
|
||||
ENV['REPLACE_ASSETS'] = 'true'
|
||||
ENV['BUILD_FOR_RELEASE'] = 'true'
|
||||
ENV['APP_SCHEME'] = 'mattermost-mobile'
|
||||
ENV['APP_SCHEME'] = 'mattermost'
|
||||
data_path = 'build-ios'
|
||||
|
||||
update_identifiers
|
||||
replace_assets
|
||||
|
||||
sh 'rm -rf ../build-ios/'
|
||||
sh 'cd ../ios && xcodebuild -workspace Mattermost.xcworkspace -scheme Mattermost -arch x86_64 -sdk iphonesimulator -configuration Release -parallelizeTargets -derivedDataPath ../build-ios ENABLE_BITCODE=NO CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO ENABLE_BITCODE=NO'
|
||||
|
||||
data_path = 'ios'
|
||||
if ENV['CIRCLECI'] == 'true'
|
||||
data_path = 'build-ios'
|
||||
end
|
||||
|
||||
sh "cd ../#{data_path}/Build/Products/Release-iphonesimulator && zip -r Mattermost-simulator-x86_64.app.zip Mattermost.app"
|
||||
sh "mv ../#{data_path}/Build/Products/Release-iphonesimulator/Mattermost-simulator-x86_64.app.zip ../"
|
||||
sh 'rm -rf ../build-ios/'
|
||||
|
||||
upload_file_to_s3({
|
||||
:os_type => "iOS",
|
||||
|
|
@ -457,16 +456,12 @@ platform :ios do
|
|||
app_group_identifiers: [app_group_id]
|
||||
)
|
||||
|
||||
find_replace_string(
|
||||
path_to_file: './ios/UploadAttachments/UploadAttachments/MMMConstants.m',
|
||||
old_string: 'group.com.mattermost.rnbeta',
|
||||
new_string: app_group_id
|
||||
)
|
||||
|
||||
find_replace_string(
|
||||
path_to_file: './node_modules/react-native-mmkv-storage/ios/MMKVStorage.m',
|
||||
old_string: 'group.com.mattermost.rnbeta',
|
||||
new_string: app_group_id
|
||||
update_info_plist(
|
||||
xcodeproj: './ios/Mattermost.xcodeproj',
|
||||
plist_path: 'Mattermost/Info.plist',
|
||||
block: proc do |plist|
|
||||
plist["AppGroupIdentifier"] = app_group_id
|
||||
end
|
||||
)
|
||||
|
||||
update_app_group_identifiers(
|
||||
|
|
@ -474,11 +469,27 @@ platform :ios do
|
|||
app_group_identifiers: [app_group_id]
|
||||
)
|
||||
|
||||
update_info_plist(
|
||||
xcodeproj: './ios/Mattermost.xcodeproj',
|
||||
plist_path: 'MattermostShare/Info.plist',
|
||||
block: proc do |plist|
|
||||
plist["AppGroupIdentifier"] = app_group_id
|
||||
end
|
||||
)
|
||||
|
||||
update_app_group_identifiers(
|
||||
entitlements_file: './ios/NotificationService/NotificationService.entitlements',
|
||||
app_group_identifiers: [app_group_id]
|
||||
)
|
||||
|
||||
update_info_plist(
|
||||
xcodeproj: './ios/Mattermost.xcodeproj',
|
||||
plist_path: 'NotificationService/Info.plist',
|
||||
block: proc do |plist|
|
||||
plist["AppGroupIdentifier"] = app_group_id
|
||||
end
|
||||
)
|
||||
|
||||
# Sync the provisioning profiles using match
|
||||
if ENV['SYNC_PROVISIONING_PROFILES'] == 'true' && !ENV['MATCH_PASSWORD'].nil? && !ENV['MATCH_PASSWORD'].empty?
|
||||
match(type: ENV['MATCH_TYPE'] || 'adhoc')
|
||||
|
|
@ -590,7 +601,7 @@ platform :android do
|
|||
ENV['APP_NAME'] = 'Mattermost'
|
||||
ENV['REPLACE_ASSETS'] = 'true'
|
||||
ENV['BUILD_FOR_RELEASE'] = 'true'
|
||||
ENV['APP_SCHEME'] = 'mattermost-mobile'
|
||||
ENV['APP_SCHEME'] = 'mattermost'
|
||||
|
||||
update_identifiers
|
||||
replace_assets
|
||||
|
|
@ -727,20 +738,37 @@ platform :android do
|
|||
gradle(
|
||||
task: 'app:assemble',
|
||||
build_type: config_mode,
|
||||
project_dir: 'android/'
|
||||
project_dir: 'android/',
|
||||
properties: {
|
||||
'separateApk' => ENV["SEPARATE_APKS"] || false,
|
||||
'universalApk' => ENV["SEPARATE_APKS"] || false,
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
def move_apk_to_root
|
||||
app_name = ENV['APP_NAME'] || 'Mattermost Beta'
|
||||
app_name_sub = app_name.gsub(" ", "_")
|
||||
new_apk_path = "#{Pathname.new(File.expand_path(File.dirname(__FILE__))).parent.to_s}/#{app_name_sub}.apk"
|
||||
apk_path = lane_context[SharedValues::GRADLE_APK_OUTPUT_PATH]
|
||||
|
||||
unless apk_path.nil?
|
||||
sh "mv #{apk_path} #{new_apk_path}"
|
||||
lane_context[SharedValues::GRADLE_APK_OUTPUT_PATH] = new_apk_path
|
||||
apks = lane_context[SharedValues::GRADLE_ALL_APK_OUTPUT_PATHS]
|
||||
outputJson = load_config_json(lane_context[SharedValues::GRADLE_OUTPUT_JSON_OUTPUT_PATH])
|
||||
paths = []
|
||||
apks.each do |apk|
|
||||
filename = File.basename(apk)
|
||||
output = outputJson.find { |o| o["path"] === filename }
|
||||
unless output.nil?
|
||||
filterName = output["apkData"]["filterName"]
|
||||
name = "#{app_name_sub}"
|
||||
unless filterName.nil? || filterName.empty?
|
||||
name += "-#{filterName}"
|
||||
end
|
||||
new_apk_path = "#{Pathname.new(File.expand_path(File.dirname(__FILE__))).parent.to_s}/#{name}.apk"
|
||||
paths.push(new_apk_path)
|
||||
sh "mv #{apk} #{new_apk_path}"
|
||||
UI.message("APK PATH \"#{new_apk_path}\", #{filterName}")
|
||||
end
|
||||
end
|
||||
|
||||
lane_context[SharedValues::GRADLE_ALL_APK_OUTPUT_PATHS] = paths
|
||||
end
|
||||
|
||||
def link_sentry_android
|
||||
|
|
@ -802,23 +830,23 @@ def send_message_to_mattermost(options)
|
|||
end
|
||||
|
||||
def submit_to_testflight(ipa_path)
|
||||
app_name = ENV['APP_NAME'] || 'Mattermost Beta'
|
||||
app_name_sub = app_name.gsub(" ", "_")
|
||||
ipa = (Dir.glob(ipa_path).select { |f| File.file? f}).first
|
||||
|
||||
if(File.file?(ipa_path))
|
||||
UI.success("ipa file #{ipa_path}")
|
||||
if !ipa.nil?
|
||||
UI.success("ipa file #{ipa}")
|
||||
pilot(
|
||||
ipa: ipa_path
|
||||
ipa: ipa
|
||||
)
|
||||
else
|
||||
UI.user_error! "ipa file does not exist #{ipa_path}"
|
||||
UI.user_error! "ipa file does not exist #{ipa}"
|
||||
return
|
||||
end
|
||||
|
||||
filename = File.basename(ipa)
|
||||
version_number = get_version_number(xcodeproj: './ios/Mattermost.xcodeproj', target: 'Mattermost')
|
||||
build_number = get_build_number(xcodeproj: './ios/Mattermost.xcodeproj')
|
||||
s3_folder = "#{ENV['AWS_FOLDER_NAME']}/#{version_number}/#{build_number}"
|
||||
public_link = "https://#{ENV['AWS_BUCKET_NAME']}/#{s3_folder}/#{app_name_sub}.ipa"
|
||||
public_link = "https://#{ENV['AWS_BUCKET_NAME']}/#{s3_folder}/#{filename}"
|
||||
|
||||
|
||||
# Send a build message to Mattermost
|
||||
|
|
@ -843,34 +871,35 @@ def submit_to_testflight(ipa_path)
|
|||
end
|
||||
|
||||
def submit_to_google_play(apk_path)
|
||||
app_name = ENV['APP_NAME'] || 'Mattermost Beta'
|
||||
app_name_sub = app_name.gsub(" ", "_")
|
||||
apks = Dir.glob(apk_path).select { |f| File.file? f}
|
||||
filenames = apks.map {|f| File.basename(f)}
|
||||
|
||||
if(File.file?(apk_path))
|
||||
UI.success("apk file #{apk_path}")
|
||||
if(apks.length > 0)
|
||||
unless ENV['SUPPLY_JSON_KEY'].nil? || ENV['SUPPLY_JSON_KEY'].empty?
|
||||
supply(
|
||||
package_name: ENV['MAIN_APP_IDENTIFIER'] || ENV['SUPPLY_PACKAGE_NAME'],
|
||||
track: ENV['SUPPLY_TRACK'] || 'alpha',
|
||||
apk: apk_path
|
||||
apk_paths: apks
|
||||
)
|
||||
end
|
||||
else
|
||||
UI.user_error! "apk file does not exist #{apk_path}"
|
||||
UI.user_error! "There are no apks in #{apk_path}"
|
||||
return
|
||||
end
|
||||
|
||||
version_number = android_get_version_name(gradle_file: './android/app/build.gradle')
|
||||
build_number = android_get_version_code(gradle_file: './android/app/build.gradle')
|
||||
s3_folder = "#{ENV['AWS_FOLDER_NAME']}/#{version_number}/#{build_number}"
|
||||
public_link = "https://#{ENV['AWS_BUCKET_NAME']}/#{s3_folder}/#{app_name_sub}.apk"
|
||||
public_path = "https://#{ENV['AWS_BUCKET_NAME']}/#{s3_folder}"
|
||||
links = (filenames.map { |f| "* #{public_path}/#{f}"}).join("\n")
|
||||
|
||||
# Send a build message to Mattermost
|
||||
pretext = '#### New Android released ready to be published'
|
||||
msg = "Release has been cut and is on the Beta track ready to be published.\nDownload link: #{public_link}"
|
||||
msg = "Release has been cut and is on the Beta track ready to be published.\nDownload links:\n#{links}"
|
||||
|
||||
if ENV['BETA_BUILD'] == 'true'
|
||||
pretext = '#### New Android beta published to Google Play'
|
||||
msg = "Sign up as a beta tester [here](https://play.google.com/apps/testing/com.mattermost.rnbeta).\nDownload link: #{public_link}"
|
||||
msg = "Sign up as a beta tester [here](https://play.google.com/apps/testing/com.mattermost.rnbeta).\nDownload links:\n#{links}"
|
||||
end
|
||||
|
||||
send_message_to_mattermost({
|
||||
|
|
@ -885,21 +914,6 @@ def submit_to_google_play(apk_path)
|
|||
})
|
||||
end
|
||||
|
||||
def submit_to_store
|
||||
apk_path = lane_context[SharedValues::GRADLE_APK_OUTPUT_PATH]
|
||||
ipa_path = lane_context[SharedValues::IPA_OUTPUT_PATH]
|
||||
|
||||
# Submit to Google Play if required
|
||||
if !apk_path.nil? && ENV['SUBMIT_ANDROID_TO_GOOGLE_PLAY'] == 'true'
|
||||
submit_to_google_play(apk_path)
|
||||
end
|
||||
|
||||
# Submit to TestFlight if required
|
||||
if !ipa_path.nil? && ENV['SUBMIT_IOS_TO_TESTFLIGHT'] == 'true'
|
||||
submit_to_testflight(ipa_path)
|
||||
end
|
||||
end
|
||||
|
||||
def qa_build_message(options)
|
||||
abbreviated_commit_hash = last_git_commit[:abbreviated_commit_hash]
|
||||
os_type = options[:os_type]
|
||||
|
|
|
|||
|
|
@ -6,22 +6,22 @@ GEM
|
|||
public_suffix (>= 2.0.2, < 5.0)
|
||||
atomos (0.1.3)
|
||||
aws-eventstream (1.1.0)
|
||||
aws-partitions (1.366.0)
|
||||
aws-sdk-core (3.105.0)
|
||||
aws-partitions (1.381.0)
|
||||
aws-sdk-core (3.109.1)
|
||||
aws-eventstream (~> 1, >= 1.0.2)
|
||||
aws-partitions (~> 1, >= 1.239.0)
|
||||
aws-sigv4 (~> 1.1)
|
||||
jmespath (~> 1.0)
|
||||
aws-sdk-kms (1.37.0)
|
||||
aws-sdk-core (~> 3, >= 3.99.0)
|
||||
aws-sdk-kms (1.39.0)
|
||||
aws-sdk-core (~> 3, >= 3.109.0)
|
||||
aws-sigv4 (~> 1.1)
|
||||
aws-sdk-s3 (1.79.1)
|
||||
aws-sdk-core (~> 3, >= 3.104.3)
|
||||
aws-sdk-s3 (1.83.0)
|
||||
aws-sdk-core (~> 3, >= 3.109.0)
|
||||
aws-sdk-kms (~> 1)
|
||||
aws-sigv4 (~> 1.1)
|
||||
aws-sigv4 (1.2.2)
|
||||
aws-eventstream (~> 1, >= 1.0.2)
|
||||
babosa (1.0.3)
|
||||
babosa (1.0.4)
|
||||
claide (1.0.3)
|
||||
colored (1.2)
|
||||
colored2 (3.1.2)
|
||||
|
|
@ -44,7 +44,7 @@ GEM
|
|||
faraday_middleware (1.0.0)
|
||||
faraday (~> 1.0)
|
||||
fastimage (2.2.0)
|
||||
fastlane (2.158.0)
|
||||
fastlane (2.162.0)
|
||||
CFPropertyList (>= 2.3, < 4.0.0)
|
||||
addressable (>= 2.3, < 3.0.0)
|
||||
aws-sdk-s3 (~> 1.0)
|
||||
|
|
@ -100,14 +100,14 @@ GEM
|
|||
google-cloud-env (1.3.3)
|
||||
faraday (>= 0.17.3, < 2.0)
|
||||
google-cloud-errors (1.0.1)
|
||||
google-cloud-storage (1.28.0)
|
||||
google-cloud-storage (1.29.1)
|
||||
addressable (~> 2.5)
|
||||
digest-crc (~> 0.4)
|
||||
google-api-client (~> 0.33)
|
||||
google-cloud-core (~> 1.2)
|
||||
googleauth (~> 0.9)
|
||||
mini_mime (~> 1.0)
|
||||
googleauth (0.13.1)
|
||||
googleauth (0.14.0)
|
||||
faraday (>= 0.17.3, < 2.0)
|
||||
jwt (>= 1.4, < 3.0)
|
||||
memoist (~> 0.16)
|
||||
|
|
@ -165,7 +165,7 @@ GEM
|
|||
unf_ext (0.0.7.7)
|
||||
unicode-display_width (1.7.0)
|
||||
word_wrap (1.0.0)
|
||||
xcodeproj (1.18.0)
|
||||
xcodeproj (1.19.0)
|
||||
CFPropertyList (>= 2.3.3, < 4.0)
|
||||
atomos (~> 0.1.3)
|
||||
claide (>= 1.0.2, < 2.0)
|
||||
|
|
@ -188,4 +188,4 @@ DEPENDENCIES
|
|||
nokogiri
|
||||
|
||||
BUNDLED WITH
|
||||
2.0.2
|
||||
2.1.4
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
source "https://rubygems.org"
|
||||
|
||||
gem "cocoapods", "1.7.5"
|
||||
gem "cocoapods", "1.10.0.rc.1"
|
||||
|
|
@ -2,23 +2,27 @@ GEM
|
|||
remote: https://rubygems.org/
|
||||
specs:
|
||||
CFPropertyList (3.0.2)
|
||||
activesupport (4.2.11.1)
|
||||
i18n (~> 0.7)
|
||||
activesupport (5.2.4.4)
|
||||
concurrent-ruby (~> 1.0, >= 1.0.2)
|
||||
i18n (>= 0.7, < 2)
|
||||
minitest (~> 5.1)
|
||||
thread_safe (~> 0.3, >= 0.3.4)
|
||||
tzinfo (~> 1.1)
|
||||
addressable (2.7.0)
|
||||
public_suffix (>= 2.0.2, < 5.0)
|
||||
algoliasearch (1.27.4)
|
||||
httpclient (~> 2.8, >= 2.8.3)
|
||||
json (>= 1.5.1)
|
||||
atomos (0.1.3)
|
||||
claide (1.0.3)
|
||||
cocoapods (1.7.5)
|
||||
activesupport (>= 4.0.2, < 5)
|
||||
cocoapods (1.10.0.rc.1)
|
||||
addressable (~> 2.6)
|
||||
claide (>= 1.0.2, < 2.0)
|
||||
cocoapods-core (= 1.7.5)
|
||||
cocoapods-core (= 1.10.0.rc.1)
|
||||
cocoapods-deintegrate (>= 1.0.3, < 2.0)
|
||||
cocoapods-downloader (>= 1.2.2, < 2.0)
|
||||
cocoapods-downloader (>= 1.4.0, < 2.0)
|
||||
cocoapods-plugins (>= 1.0.0, < 2.0)
|
||||
cocoapods-search (>= 1.0.0, < 2.0)
|
||||
cocoapods-stats (>= 1.0.0, < 2.0)
|
||||
cocoapods-trunk (>= 1.3.1, < 2.0)
|
||||
cocoapods-trunk (>= 1.4.0, < 2.0)
|
||||
cocoapods-try (>= 1.1.0, < 2.0)
|
||||
colored2 (~> 3.1)
|
||||
escape (~> 0.0.4)
|
||||
|
|
@ -27,50 +31,63 @@ GEM
|
|||
molinillo (~> 0.6.6)
|
||||
nap (~> 1.0)
|
||||
ruby-macho (~> 1.4)
|
||||
xcodeproj (>= 1.10.0, < 2.0)
|
||||
cocoapods-core (1.7.5)
|
||||
activesupport (>= 4.0.2, < 6)
|
||||
xcodeproj (>= 1.17.0, < 2.0)
|
||||
cocoapods-core (1.10.0.rc.1)
|
||||
activesupport (> 5.0, < 6)
|
||||
addressable (~> 2.6)
|
||||
algoliasearch (~> 1.0)
|
||||
concurrent-ruby (~> 1.1)
|
||||
fuzzy_match (~> 2.0.4)
|
||||
nap (~> 1.0)
|
||||
netrc (~> 0.11)
|
||||
public_suffix
|
||||
typhoeus (~> 1.0)
|
||||
cocoapods-deintegrate (1.0.4)
|
||||
cocoapods-downloader (1.3.0)
|
||||
cocoapods-downloader (1.4.0)
|
||||
cocoapods-plugins (1.0.0)
|
||||
nap
|
||||
cocoapods-search (1.0.0)
|
||||
cocoapods-stats (1.1.0)
|
||||
cocoapods-trunk (1.4.1)
|
||||
cocoapods-trunk (1.5.0)
|
||||
nap (>= 0.8, < 2.0)
|
||||
netrc (~> 0.11)
|
||||
cocoapods-try (1.1.0)
|
||||
cocoapods-try (1.2.0)
|
||||
colored2 (3.1.2)
|
||||
concurrent-ruby (1.1.5)
|
||||
concurrent-ruby (1.1.7)
|
||||
escape (0.0.4)
|
||||
ethon (0.12.0)
|
||||
ffi (>= 1.3.0)
|
||||
ffi (1.13.1)
|
||||
fourflusher (2.3.1)
|
||||
fuzzy_match (2.0.4)
|
||||
gh_inspector (1.1.3)
|
||||
i18n (0.9.5)
|
||||
httpclient (2.8.3)
|
||||
i18n (1.8.5)
|
||||
concurrent-ruby (~> 1.0)
|
||||
minitest (5.14.0)
|
||||
json (2.3.1)
|
||||
minitest (5.14.2)
|
||||
molinillo (0.6.6)
|
||||
nanaimo (0.2.6)
|
||||
nanaimo (0.3.0)
|
||||
nap (1.1.0)
|
||||
netrc (0.11.0)
|
||||
public_suffix (4.0.6)
|
||||
ruby-macho (1.4.0)
|
||||
thread_safe (0.3.6)
|
||||
tzinfo (1.2.6)
|
||||
typhoeus (1.4.0)
|
||||
ethon (>= 0.9.0)
|
||||
tzinfo (1.2.7)
|
||||
thread_safe (~> 0.1)
|
||||
xcodeproj (1.15.0)
|
||||
xcodeproj (1.18.0)
|
||||
CFPropertyList (>= 2.3.3, < 4.0)
|
||||
atomos (~> 0.1.3)
|
||||
claide (>= 1.0.2, < 2.0)
|
||||
colored2 (~> 3.1)
|
||||
nanaimo (~> 0.2.6)
|
||||
nanaimo (~> 0.3.0)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
|
||||
DEPENDENCIES
|
||||
cocoapods (= 1.7.5)
|
||||
cocoapods (= 1.10.0.rc.1)
|
||||
|
||||
BUNDLED WITH
|
||||
2.0.2
|
||||
2.1.4
|
||||
|
|
@ -2,6 +2,10 @@
|
|||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>AppGroupIdentifier</key>
|
||||
<string>group.com.mattermost.rnbeta</string>
|
||||
<key>BundleEntryFilename</key>
|
||||
<string>index.js</string>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
|
|
|
|||
|
|
@ -65,11 +65,16 @@ RCT_EXPORT_MODULE();
|
|||
return safeAreaInsets;
|
||||
}
|
||||
|
||||
- (NSDictionary *)constantsToExport {
|
||||
-(NSString *)appGroupId {
|
||||
NSBundle *bundle = [NSBundle mainBundle];
|
||||
NSString *appGroupId = [bundle objectForInfoDictionaryKey:@"AppGroupIdentifier"];
|
||||
return appGroupId;
|
||||
}
|
||||
|
||||
- (NSDictionary *)constantsToExport {
|
||||
return @{
|
||||
@"hasSafeAreaInsets": @([self hasSafeAreaInsets]),
|
||||
@"appGroupIdentifier": APP_GROUP_ID
|
||||
@"appGroupIdentifier": [self appGroupId]
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -87,7 +92,7 @@ RCT_EXPORT_MODULE();
|
|||
- (instancetype)init {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_sharedUserDefaults = [[NSUserDefaults alloc] initWithSuiteName:APP_GROUP_ID];
|
||||
_sharedUserDefaults = [[NSUserDefaults alloc] initWithSuiteName:[self appGroupId]];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(managedConfigDidChange:) name:@"managedConfigDidChange" object:nil];
|
||||
[[NSNotificationCenter defaultCenter] addObserverForName:NSUserDefaultsDidChangeNotification
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
let configurationKey = "com.apple.configuration.managed"
|
||||
|
||||
func getManagedConfig() -> [String : Any] {
|
||||
return UserDefaults.init(suiteName: APP_GROUP_ID)?.dictionary(forKey: configurationKey) ?? [:]
|
||||
let appGroupId = Bundle.main.infoDictionary!["AppGroupIdentifier"] as! String
|
||||
return UserDefaults.init(suiteName: appGroupId)?.dictionary(forKey: configurationKey) ?? [:]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@
|
|||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>AppGroupIdentifier</key>
|
||||
<string>group.com.mattermost.rnbeta</string>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@
|
|||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>AppGroupIdentifier</key>
|
||||
<string>group.com.mattermost.rnbeta</string>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
|
|
|
|||
|
|
@ -441,7 +441,7 @@ DEPENDENCIES:
|
|||
- Yoga (from `../node_modules/react-native/ReactCommon/yoga`)
|
||||
|
||||
SPEC REPOS:
|
||||
https://github.com/cocoapods/specs.git:
|
||||
https://github.com/CocoaPods/Specs.git:
|
||||
- boost-for-react-native
|
||||
- libwebp
|
||||
- MMKV
|
||||
|
|
@ -669,4 +669,4 @@ SPEC CHECKSUMS:
|
|||
|
||||
PODFILE CHECKSUM: 1aabd16b6a9ed2037b4d7443027d222817790468
|
||||
|
||||
COCOAPODS: 1.7.5
|
||||
COCOAPODS: 1.10.0.rc.1
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface MMMConstants : NSObject
|
||||
extern NSString *APP_GROUP_ID;
|
||||
extern UInt64 DEFAULT_SERVER_MAX_IMAGE_PIXELS;
|
||||
extern UInt64 DEFAULT_SERVER_MAX_FILE_SIZE;
|
||||
extern UInt64 DEFAULT_SERVER_MAX_POST_SIZE;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
#import "MMMConstants.h"
|
||||
|
||||
@implementation MMMConstants
|
||||
NSString *APP_GROUP_ID = @"group.com.mattermost.rnbeta";
|
||||
UInt64 DEFAULT_SERVER_MAX_IMAGE_PIXELS = 6048 * 4032;
|
||||
UInt64 DEFAULT_SERVER_MAX_FILE_SIZE = 50 * 1024 * 1024;
|
||||
UInt64 DEFAULT_SERVER_MAX_POST_SIZE = 4000;
|
||||
|
|
|
|||
|
|
@ -7,13 +7,19 @@
|
|||
return [[NSUserDefaults alloc] initWithSuiteName: name];
|
||||
}
|
||||
|
||||
-(NSString *)appGroupId {
|
||||
NSBundle *bundle = [NSBundle mainBundle];
|
||||
NSString *appGroupId = [bundle objectForInfoDictionaryKey:@"AppGroupIdentifier"];
|
||||
return appGroupId;
|
||||
}
|
||||
|
||||
-(NSString *)fileUrl:(NSString *)fileName {
|
||||
NSURL *fileManagerURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:APP_GROUP_ID];
|
||||
NSURL *fileManagerURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:[self appGroupId]];
|
||||
return [NSString stringWithFormat:@"%@/%@", fileManagerURL.path, fileName];
|
||||
}
|
||||
|
||||
-(id) getPreference:(NSString *)key {
|
||||
NSUserDefaults* bucket = [self bucketByName: APP_GROUP_ID];
|
||||
NSUserDefaults* bucket = [self bucketByName: [self appGroupId]];
|
||||
return [bucket objectForKey:key];
|
||||
}
|
||||
|
||||
|
|
@ -50,12 +56,12 @@
|
|||
}
|
||||
|
||||
-(void) removePreference:(NSString *)key {
|
||||
NSUserDefaults* bucket = [self bucketByName: APP_GROUP_ID];
|
||||
NSUserDefaults* bucket = [self bucketByName: [self appGroupId]];
|
||||
[bucket removeObjectForKey: key];
|
||||
}
|
||||
|
||||
-(void) setPreference:(NSString *)key value:(NSString *) value {
|
||||
NSUserDefaults* bucket = [self bucketByName: APP_GROUP_ID];
|
||||
NSUserDefaults* bucket = [self bucketByName: [self appGroupId]];
|
||||
if (bucket && [key length] > 0 && [value length] > 0) {
|
||||
[bucket setObject:value forKey:key];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -155,8 +155,10 @@
|
|||
}
|
||||
|
||||
-(NSString *)getToken {
|
||||
NSBundle *bundle = [NSBundle mainBundle];
|
||||
NSString *appGroupId = [bundle objectForInfoDictionaryKey:@"AppGroupIdentifier"];
|
||||
NSDictionary *options = @{
|
||||
@"accessGroup": APP_GROUP_ID
|
||||
@"accessGroup": appGroupId
|
||||
};
|
||||
NSString* serverUrl = [self getServerUrl];
|
||||
|
||||
|
|
|
|||
|
|
@ -55,7 +55,8 @@ import os.log
|
|||
os_log(OSLogType.default, "Mattermost Attached session with completionHandler identifier=%{public}@", identifier)
|
||||
}
|
||||
let sessionConfig = URLSessionConfiguration.background(withIdentifier: identifier)
|
||||
sessionConfig.sharedContainerIdentifier = APP_GROUP_ID
|
||||
let appGroupId = Bundle.main.infoDictionary!["AppGroupIdentifier"] as! String
|
||||
sessionConfig.sharedContainerIdentifier = appGroupId
|
||||
if #available(iOS 11.0, *) {
|
||||
sessionConfig.waitsForConnectivity = true
|
||||
}
|
||||
|
|
@ -65,7 +66,8 @@ import os.log
|
|||
|
||||
public func createURLSession(identifier: String) -> URLSession {
|
||||
let sessionConfig = URLSessionConfiguration.background(withIdentifier: identifier)
|
||||
sessionConfig.sharedContainerIdentifier = APP_GROUP_ID
|
||||
let appGroupId = Bundle.main.infoDictionary!["AppGroupIdentifier"] as! String
|
||||
sessionConfig.sharedContainerIdentifier = appGroupId
|
||||
if #available(iOS 11.0, *) {
|
||||
sessionConfig.waitsForConnectivity = true
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import Foundation
|
|||
}
|
||||
|
||||
@objc @objcMembers public class UploadSessionManager: NSObject {
|
||||
private let bucket = MattermostBucket().bucket(byName: APP_GROUP_ID)
|
||||
private let bucket = MattermostBucket().bucket(byName: Bundle.main.infoDictionary!["AppGroupIdentifier"] as! String)
|
||||
|
||||
public class var shared :UploadSessionManager {
|
||||
struct Singleton {
|
||||
|
|
@ -60,7 +60,8 @@ import Foundation
|
|||
|
||||
public func tempContainerURL() -> URL? {
|
||||
let filemgr = FileManager.default
|
||||
let containerURL = filemgr.containerURL(forSecurityApplicationGroupIdentifier: APP_GROUP_ID)
|
||||
let appGroupId = Bundle.main.infoDictionary!["AppGroupIdentifier"] as! String
|
||||
let containerURL = filemgr.containerURL(forSecurityApplicationGroupIdentifier: appGroupId)
|
||||
guard let tempDirectoryURL = containerURL?.appendingPathComponent("shareTempItems") else {return nil}
|
||||
var isDirectory = ObjCBool(false)
|
||||
let exists = filemgr.fileExists(atPath: tempDirectoryURL.path, isDirectory: &isDirectory)
|
||||
|
|
|
|||
|
|
@ -2,8 +2,6 @@
|
|||
|
||||
export NODE_OPTIONS=--max_old_space_size=12000
|
||||
export BUNDLE_COMMAND="ram-bundle"
|
||||
export NODE_BINARY=node
|
||||
|
||||
if [[ "${SENTRY_ENABLED}" = "true" ]]; then
|
||||
echo "Sentry native integration is enabled"
|
||||
|
||||
|
|
|
|||
|
|
@ -67,9 +67,6 @@ esac
|
|||
PROJECT_ROOT=${PROJECT_ROOT:-$PWD}
|
||||
cd "$PROJECT_ROOT/.." || exit
|
||||
|
||||
# Define NVM_DIR and source the nvm.sh setup script
|
||||
[ -z "$NVM_DIR" ] && export NVM_DIR="$HOME/.nvm"
|
||||
|
||||
# Define entry file
|
||||
if [[ "$ENTRY_FILE" ]]; then
|
||||
# Use ENTRY_FILE defined by user
|
||||
|
|
@ -80,27 +77,6 @@ elif [[ -s "index.ios.js" ]]; then
|
|||
ENTRY_FILE=${1:-index.js}
|
||||
fi
|
||||
|
||||
if [[ -s "$HOME/.nvm/nvm.sh" ]]; then
|
||||
. "$HOME/.nvm/nvm.sh"
|
||||
elif [[ -x "$(command -v brew)" && -s "$(brew --prefix nvm)/nvm.sh" ]]; then
|
||||
. "$(brew --prefix nvm)/nvm.sh"
|
||||
fi
|
||||
|
||||
# Set up the nodenv node version manager if present
|
||||
if [[ -x "$HOME/.nodenv/bin/nodenv" ]]; then
|
||||
eval "$("$HOME/.nodenv/bin/nodenv" init -)"
|
||||
elif [[ -x "$(command -v brew)" && -x "$(brew --prefix nodenv)/bin/nodenv" ]]; then
|
||||
eval "$("$(brew --prefix nodenv)/bin/nodenv" init -)"
|
||||
fi
|
||||
|
||||
# Set up the ndenv of anyenv if preset
|
||||
if [[ ! -x node && -d ${HOME}/.anyenv/bin ]]; then
|
||||
export PATH=${HOME}/.anyenv/bin:${PATH}
|
||||
if [[ "$(anyenv envs | grep -c ndenv )" -eq 1 ]]; then
|
||||
eval "$(anyenv init -)"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Path to react-native folder inside node_modules
|
||||
REACT_NATIVE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/node_modules/react-native" && pwd)"
|
||||
# check and assign NODE_BINARY env
|
||||
|
|
|
|||
9
package-lock.json
generated
9
package-lock.json
generated
|
|
@ -6065,15 +6065,6 @@
|
|||
"@types/react-native": "*"
|
||||
}
|
||||
},
|
||||
"@types/react-test-renderer": {
|
||||
"version": "16.9.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-test-renderer/-/react-test-renderer-16.9.3.tgz",
|
||||
"integrity": "sha512-wJ7IlN5NI82XMLOyHSa+cNN4Z0I+8/YaLl04uDgcZ+W+ExWCmCiVTLT/7fRNqzy4OhStZcUwIqLNF7q+AdW43Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/react": "*"
|
||||
}
|
||||
},
|
||||
"@types/shallow-equals": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/shallow-equals/-/shallow-equals-1.0.0.tgz",
|
||||
|
|
|
|||
23
package.json
23
package.json
|
|
@ -151,19 +151,30 @@
|
|||
}
|
||||
},
|
||||
"scripts": {
|
||||
"start": "node ./node_modules/react-native/local-cli/cli.js start",
|
||||
"check": "eslint --ignore-path .gitignore --ignore-pattern node_modules --quiet . && npm run tsc",
|
||||
"fix": "eslint --ignore-path .gitignore --ignore-pattern node_modules --quiet . --fix",
|
||||
"postinstall": "make post-install",
|
||||
"android": "react-native run-android",
|
||||
"ios": "react-native run-ios",
|
||||
"start": "react-native start",
|
||||
"check": "npm run lint && npm run tsc",
|
||||
"clean": "./scripts/clean.sh",
|
||||
"ios-gems": "cd ios && bundle install",
|
||||
"fix": "npm run lint -- --fix",
|
||||
"lint": "eslint --ignore-path .gitignore --ignore-pattern node_modules --quiet .",
|
||||
"pod-install": "cd ios && bundle exec pod install",
|
||||
"postinstall": "patch-package && ./scripts/postinstall.sh",
|
||||
"tsc": "NODE_OPTIONS=--max_old_space_size=12000 tsc --noEmit",
|
||||
"test": "jest --forceExit --runInBand --detectOpenHandles",
|
||||
"test:watch": "jest --watch --runInBand --detectOpenHandles",
|
||||
"test:watch": "npm test -- --watch",
|
||||
"test:coverage": "jest --coverage",
|
||||
"updatesnapshot": "jest --updateSnapshot",
|
||||
"mmjstool": "mmjstool",
|
||||
"i18n-extract": "npm run mmjstool -- i18n extract-mobile",
|
||||
"i18n-clean-empty": "npm run mmjstool -- i18n clean-empty --mobile-dir .",
|
||||
"e2e:android": "cd detox && npm run e2e:android-build && npm run e2e:android-test && cd ..",
|
||||
"e2e:ios": "cd detox && npm run e2e:ios-test && cd .."
|
||||
"e2e:ios": "cd detox && npm run e2e:ios-test && cd ..",
|
||||
"build:ios": "./scripts/build.sh ipa",
|
||||
"build:ios-unsigned": "./scripts/build.sh ipa unsigned",
|
||||
"build:ios-sim": "./scripts/build.sh ipa simulator",
|
||||
"build:android": "./scripts/build.sh apk",
|
||||
"build:android-unsigned": "./scripts/build.sh apk unsigned"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,14 @@
|
|||
diff --git a/node_modules/react-native-mmkv-storage/ios/MMKVStorage.m b/node_modules/react-native-mmkv-storage/ios/MMKVStorage.m
|
||||
index 34c764c..34fd83d 100644
|
||||
index fe0ee2b..5bdde1d 100644
|
||||
--- a/node_modules/react-native-mmkv-storage/ios/MMKVStorage.m
|
||||
+++ b/node_modules/react-native-mmkv-storage/ios/MMKVStorage.m
|
||||
@@ -37,7 +37,9 @@ - (id)init
|
||||
@@ -45,7 +45,10 @@ - (id)init
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
- [MMKV initialize];
|
||||
+ NSString *APP_GROUP_ID = @"group.com.mattermost.rnbeta";
|
||||
+ NSBundle *bundle = [NSBundle mainBundle];
|
||||
+ NSString *APP_GROUP_ID = [bundle objectForInfoDictionaryKey:@"AppGroupIdentifier"];
|
||||
+ NSString *groupDir = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:APP_GROUP_ID].path;
|
||||
+ [MMKV initializeMMKV:nil groupDir:groupDir logLevel:MMKVLogInfo];
|
||||
secureStorage = [[SecureStorage alloc]init];
|
||||
|
|
|
|||
97
scripts/build.sh
Executable file
97
scripts/build.sh
Executable file
|
|
@ -0,0 +1,97 @@
|
|||
#!/bin/sh
|
||||
|
||||
function execute() {
|
||||
cd fastlane && NODE_ENV=production bundle exec fastlane $1 $2
|
||||
}
|
||||
|
||||
function apk() {
|
||||
case $1 in
|
||||
unsigned)
|
||||
echo "Building Android unsigned app"
|
||||
setup android
|
||||
execute android unsigned
|
||||
;;
|
||||
*)
|
||||
echo "Building Android app"
|
||||
setup android
|
||||
execute android build
|
||||
esac
|
||||
}
|
||||
|
||||
function ipa() {
|
||||
case $1 in
|
||||
unsigned)
|
||||
echo "Building iOS unsigned app"
|
||||
setup ios
|
||||
execute ios unsigned
|
||||
;;
|
||||
simulator)
|
||||
echo "Building unsigned x86_64 iOS app for iPhone simulator"
|
||||
setup ios
|
||||
execute ios simulator
|
||||
;;
|
||||
*)
|
||||
echo "Building iOS app"
|
||||
setup ios
|
||||
execute ios build
|
||||
esac
|
||||
}
|
||||
|
||||
function setup() {
|
||||
if [[ -z "$SKIP_SETUP" ]]; then
|
||||
npm run clean || exit 1
|
||||
npm install --ignore-scripts || exit 1
|
||||
npx patch-package || exit 1
|
||||
|
||||
if [[ "$1" == "ios"* ]]; then
|
||||
echo "Installing Gems"
|
||||
npm run ios-gems &> /dev/null || exit 1
|
||||
echo "Getting Cocoapods dependencies"
|
||||
npm run pod-install || exit 1
|
||||
fi
|
||||
|
||||
ASSETS=$(node scripts/generate-assets.js)
|
||||
if [ -z "$ASSETS" ]; then
|
||||
echo "Error Generating app assets"
|
||||
exit 1
|
||||
else
|
||||
echo "Generating app assets"
|
||||
fi
|
||||
|
||||
echo "Installing Fastane"
|
||||
if !gem list bundler -i --version 2.1.4 > /dev/null 2>&1; then
|
||||
gem install bundler --versio 2.1.4
|
||||
fi
|
||||
cd fastlane && bundle install && cd .. || exit 1
|
||||
fi
|
||||
|
||||
if [ "$1" = "android" ]; then
|
||||
./node_modules/.bin/jetify
|
||||
fi
|
||||
}
|
||||
|
||||
case $1 in
|
||||
apk)
|
||||
apk $2
|
||||
;;
|
||||
ipa)
|
||||
if [[ "$OSTYPE" == "darwin"* ]]; then
|
||||
ipa $2
|
||||
else
|
||||
echo "You need a MacOS to build the iOS mobile app"
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
echo "Build the mobile app for Android or iOS
|
||||
Usage: build.sh <type> [options]
|
||||
|
||||
Type:
|
||||
apk Builds Android APK(s)
|
||||
ipa Builds iOS IPA
|
||||
|
||||
Options:
|
||||
apk: unsigned
|
||||
ipa: unsigned or simulator"
|
||||
;;
|
||||
esac
|
||||
11
scripts/clean.sh
Executable file
11
scripts/clean.sh
Executable file
|
|
@ -0,0 +1,11 @@
|
|||
#!/bin/sh
|
||||
|
||||
echo Cleaning started
|
||||
|
||||
rm -rf ios/Pods
|
||||
rm -rf node_modules
|
||||
rm -rf dist
|
||||
rm -rf ios/build
|
||||
rm -rf android/app/build
|
||||
|
||||
echo Cleanup finished
|
||||
|
|
@ -4,6 +4,7 @@
|
|||
/* eslint-disable no-console */
|
||||
|
||||
const fs = require('fs');
|
||||
const fsPath = require('path');
|
||||
|
||||
// Takes the files in rootA/path, overwrites or merges them with the corresponding file in rootB/path, and places the
|
||||
// resulting file in dest/path. JSON files that exist in both places are shallowly (TODO maybe deeply) merged and all
|
||||
|
|
@ -13,7 +14,7 @@ function leftMergeDirs(rootA, rootB, dest, path) {
|
|||
const pathB = rootB + path;
|
||||
|
||||
try {
|
||||
fs.mkdirSync(dest + path);
|
||||
fs.mkdirSync(dest + path, {recursive: true});
|
||||
} catch (e) {
|
||||
if (e.code !== 'EEXIST') {
|
||||
console.error('Failed to create destination dir ' + dest + path);
|
||||
|
|
@ -83,6 +84,25 @@ function leftMergeDirs(rootA, rootB, dest, path) {
|
|||
}
|
||||
}
|
||||
|
||||
const rmdir = (path) => {
|
||||
const list = fs.readdirSync(path);
|
||||
for (let i = 0; i < list.length; i++) {
|
||||
const filename = fsPath.join(path, list[i]);
|
||||
const stat = fs.statSync(filename);
|
||||
|
||||
if (stat.isDirectory()) {
|
||||
rmdir(filename);
|
||||
} else {
|
||||
fs.unlinkSync(filename);
|
||||
}
|
||||
}
|
||||
fs.rmdirSync(path);
|
||||
};
|
||||
|
||||
if (fs.existsSync('dist')) {
|
||||
rmdir('dist');
|
||||
}
|
||||
|
||||
// Assumes dist/assets exists and is empty
|
||||
leftMergeDirs('assets/base/', 'assets/override/', 'dist/assets/', '');
|
||||
/* eslint-enable no-console */
|
||||
19
scripts/postinstall.sh
Executable file
19
scripts/postinstall.sh
Executable file
|
|
@ -0,0 +1,19 @@
|
|||
#!/bin/sh
|
||||
|
||||
if [[ "$OSTYPE" == "darwin"* ]]; then
|
||||
if !gem list bundler -i --version 2.1.4 > /dev/null 2>&1; then
|
||||
gem install bundler --version 2.1.4
|
||||
fi
|
||||
echo "Installing Gems"
|
||||
npm run ios-gems &> /dev/null
|
||||
echo "Getting Cocoapods dependencies"
|
||||
npm run pod-install &> /dev/null
|
||||
fi
|
||||
|
||||
ASSETS=$(node scripts/generate-assets.js)
|
||||
if [ -z "$ASSETS" ]; then
|
||||
echo "Error Generating app assets"
|
||||
exit 1
|
||||
else
|
||||
echo "Generating app assets"
|
||||
fi
|
||||
|
|
@ -1,6 +1,8 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
/* eslint-disable react/no-multi-comp */
|
||||
|
||||
import * as ReactNative from 'react-native';
|
||||
import MockAsyncStorage from 'mock-async-storage';
|
||||
import {configure} from 'enzyme';
|
||||
|
|
@ -110,8 +112,31 @@ jest.doMock('react-native', () => {
|
|||
}, ReactNative);
|
||||
});
|
||||
|
||||
jest.mock('react-native-vector-icons/MaterialIcons', () => ({
|
||||
getImageSource: jest.fn().mockResolvedValue({}),
|
||||
}));
|
||||
jest.mock('react-native-vector-icons/MaterialCommunityIcons');
|
||||
jest.mock('react-native-vector-icons/FontAwesome5');
|
||||
jest.mock('react-native-vector-icons', () => {
|
||||
const React = jest.requireActual('react');
|
||||
const PropTypes = jest.requireActual('prop-types');
|
||||
class CompassIcon extends React.PureComponent {
|
||||
render() {
|
||||
return React.createElement('Icon', this.props);
|
||||
}
|
||||
}
|
||||
CompassIcon.propTypes = {
|
||||
name: PropTypes.string,
|
||||
size: PropTypes.number,
|
||||
style: PropTypes.oneOfType([PropTypes.array, PropTypes.number, PropTypes.object]),
|
||||
};
|
||||
CompassIcon.getImageSource = jest.fn().mockResolvedValue({});
|
||||
return {
|
||||
createIconSet: () => CompassIcon,
|
||||
|
||||
createIconSetFromFontello: () => CompassIcon,
|
||||
};
|
||||
});
|
||||
|
||||
jest.mock('react-native/Libraries/Animated/src/NativeAnimatedHelper');
|
||||
jest.mock('../node_modules/react-native/Libraries/EventEmitter/NativeEventEmitter');
|
||||
|
|
|
|||
Loading…
Reference in a new issue