mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-10-31 08:15:24 +00:00
1da4c0302e
ClassicAppManager migrates an existing user's session and encryption keys by reading the legacy app's app-group container and keychain. Those identifiers defaulted to Element's own, which this team cannot provision, so loadAccounts() threw invalidAppGroupIdentifier — caught and logged, never surfaced. Since both apps share a bundle id, the result would be every existing user silently logged out and losing local history when they update. The legacy identifiers belong to HealthChat and are provisionable under the same team, so repoint them rather than dropping them. Also stop sending accounts without key backup to a dead end. Upstream shows those users a sheet asking them to open Element Classic and set up backup first, but this update replaces that app and nothing registers its URL scheme, so the sheet's only button does nothing. Sign in directly instead: the user re-verifies the device and loses only history that by definition has no backup.
304 lines
11 KiB
YAML
304 lines
11 KiB
YAML
name: ElementX
|
|
|
|
schemes:
|
|
ElementX:
|
|
analyze:
|
|
config: Debug
|
|
archive:
|
|
config: Release
|
|
build:
|
|
targets:
|
|
ElementX:
|
|
- running
|
|
- testing
|
|
- profiling
|
|
- analyzing
|
|
- archiving
|
|
profile:
|
|
config: Release
|
|
run:
|
|
config: Debug
|
|
environmentVariables:
|
|
- variable: HTTPS_PROXY
|
|
value: localhost:9090
|
|
isEnabled: false
|
|
- variable: HTTP_PROXY
|
|
value: localhost:9090
|
|
isEnabled: false
|
|
- variable: UI_TESTS_SCREEN
|
|
value: ""
|
|
isEnabled: false
|
|
- variable: RESET_APP_SETTINGS
|
|
value: "true"
|
|
isEnabled: false
|
|
test:
|
|
config: Debug
|
|
gatherCoverageData: true
|
|
coverageTargets:
|
|
- ElementX
|
|
testPlans:
|
|
- path: ../../UnitTests/SupportingFiles/UnitTests.xctestplan
|
|
defaultPlan: true
|
|
|
|
targets:
|
|
ElementX:
|
|
type: application
|
|
platform: iOS
|
|
|
|
info:
|
|
path: Info.plist
|
|
properties:
|
|
UILaunchScreen:
|
|
UIColorName: colors/background-color
|
|
CFBundleDisplayName: $(APP_DISPLAY_NAME)
|
|
# HealthChat: without this CFBundleName defaults to $(PRODUCT_NAME) (ElementX, kept for the module
|
|
# name), which is what the web authentication session's sign-in alert shows — not CFBundleDisplayName.
|
|
CFBundleName: $(APP_DISPLAY_NAME)
|
|
CFBundleShortVersionString: $(MARKETING_VERSION)
|
|
CFBundleVersion: $(CURRENT_PROJECT_VERSION)
|
|
CFBundleURLTypes: [
|
|
{
|
|
CFBundleTypeRole: Editor,
|
|
CFBundleURLName: "Application",
|
|
CFBundleURLSchemes: [
|
|
$(BASE_BUNDLE_IDENTIFIER), # The app's own scheme for custom routes
|
|
"matrix" # Matrix URI scheme for permalinks
|
|
]
|
|
}
|
|
]
|
|
UIApplicationSceneManifest: {
|
|
UIApplicationSupportsMultipleScenes: true
|
|
}
|
|
UISupportedInterfaceOrientations: [
|
|
UIInterfaceOrientationPortrait,
|
|
UIInterfaceOrientationPortraitUpsideDown,
|
|
UIInterfaceOrientationLandscapeLeft,
|
|
UIInterfaceOrientationLandscapeRight
|
|
]
|
|
appGroupIdentifier: $(APP_GROUP_IDENTIFIER)
|
|
baseBundleIdentifier: $(BASE_BUNDLE_IDENTIFIER)
|
|
keychainAccessGroupIdentifier: $(KEYCHAIN_ACCESS_GROUP_IDENTIFIER)
|
|
classicAppGroupIdentifier: $(CLASSIC_APP_GROUP_IDENTIFIER)
|
|
classicAppKeychainServiceIdentifier: $(CLASSIC_APP_KEYCHAIN_SERVICE_IDENTIFIER)
|
|
classicAppKeychainAccessGroupIdentifier: $(CLASSIC_APP_KEYCHAIN_ACCESS_GROUP_IDENTIFIER)
|
|
classicAppDeepLinkURL: $(CLASSIC_APP_DEEP_LINK_URL)
|
|
productionAppName: $(PRODUCTION_APP_NAME)
|
|
isNightlyBuild: $(IS_NIGHTLY_BUILD)
|
|
ITSAppUsesNonExemptEncryption: false
|
|
NSUserActivityTypes: [
|
|
INSendMessageIntent,
|
|
INStartCallIntent,
|
|
]
|
|
NSCameraUsageDescription: To take pictures or videos and send them as a message $(APP_DISPLAY_NAME) needs access to the camera.
|
|
NSMicrophoneUsageDescription: To record and send messages with audio, $(APP_DISPLAY_NAME) needs to access the microphone.
|
|
NSPhotoLibraryAddUsageDescription: This lets you save images and videos to your photo library.
|
|
NSLocationWhenInUseUsageDescription: Grant location access so that $(APP_DISPLAY_NAME) can share your location.
|
|
NSLocationAlwaysAndWhenInUseUsageDescription: To share your live location, $(APP_DISPLAY_NAME) needs location access when the app is in the background.
|
|
NSFaceIDUsageDescription: Face ID is used to access your app.
|
|
UIBackgroundModes: [
|
|
audio,
|
|
fetch,
|
|
processing,
|
|
voip,
|
|
location
|
|
]
|
|
BGTaskSchedulerPermittedIdentifiers: [
|
|
io.element.elementx.background.refresh,
|
|
io.element.elementx.background.search-backfill
|
|
]
|
|
UTExportedTypeDeclarations:
|
|
- UTTypeConformsTo: [public.text]
|
|
UTTypeDescription: Mention Pills
|
|
UTTypeIdentifier: $(PILLS_UT_TYPE_IDENTIFIER)
|
|
CFBundleDocumentTypes:
|
|
- CFBundleTypeName: Mention Pills
|
|
CFBundleTypeRole: Viewer
|
|
LSHandlerRank: Owner
|
|
LSItemContentTypes: $(PILLS_UT_TYPE_IDENTIFIER)
|
|
LSSupportsOpeningDocumentsInPlace: false
|
|
|
|
entitlements:
|
|
path: ElementX.entitlements
|
|
properties:
|
|
aps-environment: development
|
|
com.apple.developer.associated-domains:
|
|
# HealthChat: app.healthchat.ch universal links + webcredentials (OAuth/autofill). matrix.to kept for permalinks.
|
|
- applinks:app.healthchat.ch
|
|
- applinks:matrix.to
|
|
- webcredentials:*.healthchat.ch
|
|
com.apple.developer.usernotifications.communication: true
|
|
com.apple.security.app-sandbox: true
|
|
com.apple.security.application-groups:
|
|
# HealthChat: dropped $(CLASSIC_APP_GROUP_IDENTIFIER) — not because it is un-provisionable,
|
|
# but because it resolves to group.ch.healthchat, the same value as $(APP_GROUP_IDENTIFIER)
|
|
# below. The legacy container is already entitled; listing it twice would duplicate the entry.
|
|
- $(APP_GROUP_IDENTIFIER)
|
|
com.apple.security.network.client: true
|
|
keychain-access-groups:
|
|
- $(KEYCHAIN_ACCESS_GROUP_IDENTIFIER)
|
|
# HealthChat: the legacy app's keychain group. ClassicAppManager reads the account and
|
|
# crypto-store keys from here to migrate existing users. Same team prefix, so it is
|
|
# provisionable — unlike Element's im.vector.app.* default in app.yml.
|
|
- $(CLASSIC_APP_KEYCHAIN_ACCESS_GROUP_IDENTIFIER)
|
|
|
|
settings:
|
|
base:
|
|
PRODUCT_NAME: $(APP_NAME)
|
|
PRODUCT_BUNDLE_IDENTIFIER: $(BASE_BUNDLE_IDENTIFIER)
|
|
MARKETING_VERSION: $(MARKETING_VERSION)
|
|
CURRENT_PROJECT_VERSION: $(CURRENT_PROJECT_VERSION)
|
|
ASSETCATALOG_COMPILER_APPICON_NAME: AppIcon
|
|
DEVELOPMENT_TEAM: $(DEVELOPMENT_TEAM)
|
|
SWIFT_OBJC_BRIDGING_HEADER: ElementX/SupportingFiles/ElementX-Bridging-Header.h
|
|
SWIFT_OBJC_INTERFACE_HEADER_NAME: GeneratedInterface-Swift.h
|
|
PILLS_UT_TYPE_IDENTIFIER: $(BASE_BUNDLE_IDENTIFIER).pills
|
|
DEVELOPMENT_ASSET_PATHS: Components/DevelopmentAssets/Media
|
|
SWIFT_VERSION: 6
|
|
SWIFT_APPROACHABLE_CONCURRENCY: YES
|
|
SWIFT_DEFAULT_ACTOR_ISOLATION: MainActor
|
|
OTHER_SWIFT_FLAGS:
|
|
- "-DIS_MAIN_APP"
|
|
|
|
preBuildScripts:
|
|
- name: 🛠 SwiftGen
|
|
runOnlyWhenInstalling: false
|
|
basedOnDependencyAnalysis: false
|
|
shell: /bin/sh
|
|
script: |
|
|
export PATH="$PATH:/opt/homebrew/bin"
|
|
if which swiftgen >/dev/null; then
|
|
swiftgen config run --config Tools/SwiftGen/swiftgen-config.yml
|
|
else
|
|
echo "warning: SwiftGen not installed, download from https://github.com/SwiftGen/SwiftGen"
|
|
fi
|
|
- name: 🧙 Sourcery - Generate mocks
|
|
runOnlyWhenInstalling: false
|
|
basedOnDependencyAnalysis: false
|
|
shell: /bin/sh
|
|
script: |
|
|
export PATH="$PATH:/opt/homebrew/bin"
|
|
if which sourcery >/dev/null; then
|
|
sourcery --config Tools/Sourcery/AutoMockableConfig.yml
|
|
else
|
|
echo "warning: Sourcery not installed, run swift run tools setup-project"
|
|
fi
|
|
|
|
- name: 🧙 Sourcery - Generate preview tests
|
|
runOnlyWhenInstalling: false
|
|
basedOnDependencyAnalysis: false
|
|
shell: /bin/sh
|
|
script: |
|
|
export PATH="$PATH:/opt/homebrew/bin"
|
|
if which sourcery >/dev/null; then
|
|
sourcery --config Tools/Sourcery/PreviewTestsConfig.yml
|
|
else
|
|
echo "warning: Sourcery not installed, run swift run tools setup-project"
|
|
fi
|
|
|
|
- name: 🧙 Sourcery - Generate Accessibility Tests
|
|
runOnlyWhenInstalling: false
|
|
basedOnDependencyAnalysis: false
|
|
shell: /bin/sh
|
|
script: |
|
|
export PATH="$PATH:/opt/homebrew/bin"
|
|
if which sourcery >/dev/null; then
|
|
sourcery --config Tools/Sourcery/TestablePreviewsDictionary.yml
|
|
sourcery --config Tools/Sourcery/AccessibilityTests.yml
|
|
else
|
|
echo "warning: Sourcery not installed, run swift run tools setup-project"
|
|
fi
|
|
|
|
postBuildScripts:
|
|
- name: ⚠️ SwiftLint
|
|
runOnlyWhenInstalling: false
|
|
basedOnDependencyAnalysis: false
|
|
shell: /bin/sh
|
|
script: |
|
|
export PATH="$PATH:/opt/homebrew/bin"
|
|
if which swiftlint >/dev/null; then
|
|
swiftlint
|
|
else
|
|
echo "warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint"
|
|
fi
|
|
- name: 🧹 SwiftFormat
|
|
runOnlyWhenInstalling: false
|
|
basedOnDependencyAnalysis: false
|
|
shell: /bin/sh
|
|
script: |
|
|
export PATH="$PATH:/opt/homebrew/bin"
|
|
if which swiftformat >/dev/null; then
|
|
swiftformat --lint --lenient "$PROJECT_DIR"
|
|
else
|
|
echo "warning: SwiftFormat not installed, download from https://github.com/nicklockwood/SwiftFormat"
|
|
fi
|
|
|
|
dependencies:
|
|
- target: NSE
|
|
- target: ShareExtension
|
|
- target: MatrixRustSDKMocks
|
|
- package: MatrixRustSDK
|
|
embed: true
|
|
- package: Compound
|
|
- package: BuildExtensions
|
|
product: Macros
|
|
- package: Algorithms
|
|
- package: AsyncAlgorithms
|
|
- package: AnalyticsEvents
|
|
- package: Collections
|
|
- package: DeviceKit
|
|
- package: EmbeddedElementCall
|
|
- package: KeychainAccess
|
|
- package: Kingfisher
|
|
- package: KZFileWatchers
|
|
- package: LoremSwiftum
|
|
- package: LRUCache
|
|
- package: Mantis
|
|
- target: MapLibreInterface
|
|
embed: true
|
|
# Embedded but not linked, dlopen'd on first map use
|
|
- target: MapLibreShim
|
|
link: false
|
|
embed: true
|
|
# The app just embeds the framework so it's in the bundle for the shim's load
|
|
# command to resolve against.
|
|
- framework: ../../MapLibre.framework
|
|
implicit: true
|
|
link: false
|
|
embed: true
|
|
- package: ElementCall
|
|
product: ElementCall
|
|
- package: PostHog
|
|
- package: SwiftState
|
|
- package: GZIP
|
|
- package: Sentry
|
|
products:
|
|
- Sentry
|
|
- SentrySwiftUI
|
|
- package: Version
|
|
- package: Emojibase
|
|
- package: WysiwygComposer
|
|
- package: SwiftOGG
|
|
- package: SwiftSoup
|
|
- package: SwiftFlow
|
|
product: Flow
|
|
- package: DSWaveformImage
|
|
product: DSWaveformImageViews
|
|
|
|
sources:
|
|
- path: ../Sources
|
|
excludes:
|
|
- Other/Extensions/XCTestCase.swift
|
|
- Other/Extensions/XCUIElement.swift
|
|
- path: ../../Components/Secrets/Secrets.swift
|
|
- path: ../Resources
|
|
- path: ../SupportingFiles
|
|
- path: ../../Tools/Scripts/Templates/SimpleScreenExample/ElementX
|
|
- path: ../../Components/DevelopmentAssets/Media
|
|
|
|
# This is required for testing purposes... The problem with unit tests is that if you
|
|
# try to `@testable import NSE` you can only get the definition of files, but due to a
|
|
# limitation in how they work, they can only compile files that are part of the main test
|
|
# target, so linking will fail. The solution is to just have the main app to reference the
|
|
# extension code, and test it directly.
|
|
- path: ../../NSE/Sources
|