Compare commits
5
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
11fb7aed76 | ||
|
|
67408e02ae | ||
|
|
dda92223d6 | ||
|
|
abd2a557e9 | ||
|
|
a50d12722f |
@@ -1,96 +1,108 @@
|
||||
{
|
||||
"sourceLanguage": "en",
|
||||
"strings": {
|
||||
"CFBundleDisplayName": {
|
||||
"comment": "App name under the icon. Brand, not translated.",
|
||||
"extractionState": "extracted_with_value",
|
||||
"localizations": {
|
||||
"en": {
|
||||
"stringUnit": {
|
||||
"state": "new",
|
||||
"value": "Flamenet"
|
||||
"sourceLanguage" : "en",
|
||||
"strings" : {
|
||||
"CFBundleDisplayName" : {
|
||||
"comment" : "App name under the icon. Brand, not translated.",
|
||||
"extractionState" : "extracted_with_value",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "new",
|
||||
"value" : "Flamenet"
|
||||
}
|
||||
},
|
||||
"es": {
|
||||
"stringUnit": {
|
||||
"state": "needs_review",
|
||||
"value": "Flamenet"
|
||||
"es" : {
|
||||
"stringUnit" : {
|
||||
"state" : "needs_review",
|
||||
"value" : "Flamenet"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"NSCameraUsageDescription": {
|
||||
"comment": "Permission prompt. DRAFT, needs native review.",
|
||||
"extractionState": "extracted_with_value",
|
||||
"localizations": {
|
||||
"en": {
|
||||
"stringUnit": {
|
||||
"state": "new",
|
||||
"value": "Flamenet uses the camera to scan a contact's address code. Nothing is recorded and no image leaves your device."
|
||||
}
|
||||
},
|
||||
"es": {
|
||||
"stringUnit": {
|
||||
"state": "needs_review",
|
||||
"value": "Flamenet usa la cámara para escanear el código de dirección de un contacto. No se graba nada y ninguna imagen sale de tu dispositivo."
|
||||
"CFBundleName" : {
|
||||
"comment" : "Bundle name",
|
||||
"extractionState" : "extracted_with_value",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "new",
|
||||
"value" : "FlamenetMessenger"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"NSFaceIDUsageDescription": {
|
||||
"comment": "Permission prompt. DRAFT, needs native review.",
|
||||
"extractionState": "extracted_with_value",
|
||||
"localizations": {
|
||||
"en": {
|
||||
"stringUnit": {
|
||||
"state": "new",
|
||||
"value": "Flamenet can require Face ID before opening the app, so somebody holding your unlocked phone cannot read your conversations."
|
||||
"NSCameraUsageDescription" : {
|
||||
"comment" : "Permission prompt. DRAFT, needs native review.",
|
||||
"extractionState" : "extracted_with_value",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "new",
|
||||
"value" : "Flamenet uses the camera to scan a contact's address code. Nothing is recorded and no image leaves your device."
|
||||
}
|
||||
},
|
||||
"es": {
|
||||
"stringUnit": {
|
||||
"state": "needs_review",
|
||||
"value": "Flamenet puede pedir Face ID antes de abrir la aplicación, para que nadie que tenga tu teléfono desbloqueado en la mano pueda leer tus conversaciones."
|
||||
"es" : {
|
||||
"stringUnit" : {
|
||||
"state" : "needs_review",
|
||||
"value" : "Flamenet usa la cámara para escanear el código de dirección de un contacto. No se graba nada y ninguna imagen sale de tu dispositivo."
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"NSMicrophoneUsageDescription": {
|
||||
"comment": "Permission prompt. DRAFT, needs native review.",
|
||||
"extractionState": "extracted_with_value",
|
||||
"localizations": {
|
||||
"en": {
|
||||
"stringUnit": {
|
||||
"state": "new",
|
||||
"value": "Flamenet uses the microphone for voice notes and voice calls, which are end-to-end encrypted before they leave your device."
|
||||
"NSFaceIDUsageDescription" : {
|
||||
"comment" : "Permission prompt. DRAFT, needs native review.",
|
||||
"extractionState" : "extracted_with_value",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "new",
|
||||
"value" : "Flamenet can require Face ID before opening the app, so somebody holding your unlocked phone cannot read your conversations."
|
||||
}
|
||||
},
|
||||
"es": {
|
||||
"stringUnit": {
|
||||
"state": "needs_review",
|
||||
"value": "Flamenet usa el micrófono para las notas de voz y las llamadas de voz, que se cifran de extremo a extremo antes de salir de tu dispositivo."
|
||||
"es" : {
|
||||
"stringUnit" : {
|
||||
"state" : "needs_review",
|
||||
"value" : "Flamenet puede pedir Face ID antes de abrir la aplicación, para que nadie que tenga tu teléfono desbloqueado en la mano pueda leer tus conversaciones."
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"NSPhotoLibraryAddUsageDescription": {
|
||||
"comment": "Permission prompt. DRAFT, needs native review.",
|
||||
"extractionState": "extracted_with_value",
|
||||
"localizations": {
|
||||
"en": {
|
||||
"stringUnit": {
|
||||
"state": "new",
|
||||
"value": "Flamenet can save a story you posted yourself to your photos, so you keep it after it disappears for everyone else. It only ever adds; it cannot see the photos you already have."
|
||||
"NSMicrophoneUsageDescription" : {
|
||||
"comment" : "Permission prompt. DRAFT, needs native review.",
|
||||
"extractionState" : "extracted_with_value",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "new",
|
||||
"value" : "Flamenet uses the microphone for voice notes and voice calls, which are end-to-end encrypted before they leave your device."
|
||||
}
|
||||
},
|
||||
"es": {
|
||||
"stringUnit": {
|
||||
"state": "needs_review",
|
||||
"value": "Flamenet puede guardar en tus fotos una historia que publicaste tú, para que la conserves cuando desaparezca para todos los demás. Solo puede agregar; no puede ver las fotos que ya tienes."
|
||||
"es" : {
|
||||
"stringUnit" : {
|
||||
"state" : "needs_review",
|
||||
"value" : "Flamenet usa el micrófono para las notas de voz y las llamadas de voz, que se cifran de extremo a extremo antes de salir de tu dispositivo."
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"NSPhotoLibraryAddUsageDescription" : {
|
||||
"comment" : "Permission prompt. DRAFT, needs native review.",
|
||||
"extractionState" : "extracted_with_value",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "new",
|
||||
"value" : "Flamenet can save a story you posted yourself to your photos, so you keep it after it disappears for everyone else. It only ever adds; it cannot see the photos you already have."
|
||||
}
|
||||
},
|
||||
"es" : {
|
||||
"stringUnit" : {
|
||||
"state" : "needs_review",
|
||||
"value" : "Flamenet puede guardar en tus fotos una historia que publicaste tú, para que la conserves cuando desaparezca para todos los demás. Solo puede agregar; no puede ver las fotos que ya tienes."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"version": "1.0"
|
||||
"version" : "1.0"
|
||||
}
|
||||
+12775
-12771
File diff suppressed because it is too large
Load Diff
@@ -4,8 +4,10 @@
|
||||
# FN_SHOT_HANDLE=… FN_SHOT_PASSPHRASE=… Scripts/store-shots.sh [device type]
|
||||
#
|
||||
# One simulator, one sign-in, one shot per tab. The device decides the pixel
|
||||
# size, so the default is an iPhone 13 Pro Max: 1284 x 2778, which is a size
|
||||
# App Store Connect accepts. Results land in build/store-shots/ and the script
|
||||
# size, so the default is an iPhone 16 Pro Max: 1320 x 2868, the 6.9 inch
|
||||
# slot. Since 2026-10-20 App Store Connect refuses 1284 x 2778 there. For
|
||||
# iPad pass com.apple.CoreSimulator.SimDeviceType.iPad-Pro-12-9-inch-6th-generation-8GB
|
||||
# (2048 x 2732). Results land in build/store-shots/ and the script
|
||||
# prints the size of each, so a wrong device is visible without opening one.
|
||||
#
|
||||
# The conversation shot is not here. It needs a second phone to talk to, so it
|
||||
@@ -13,7 +15,7 @@
|
||||
set -uo pipefail
|
||||
cd "$(dirname "$0")/.."
|
||||
|
||||
DEVICE="${1:-com.apple.CoreSimulator.SimDeviceType.iPhone-13-Pro-Max}"
|
||||
DEVICE="${1:-com.apple.CoreSimulator.SimDeviceType.iPhone-16-Pro-Max}"
|
||||
RELAY="${FN_SHOT_RELAY:-https://relay1.flamenet.io}"
|
||||
HANDLE="${FN_SHOT_HANDLE:-}"
|
||||
PASS="${FN_SHOT_PASSPHRASE:-}"
|
||||
|
||||
@@ -542,13 +542,13 @@ final class E2EInbox: ObservableObject {
|
||||
|
||||
/// Section 17.6 and 8.9d, see `E2EInbox+AccountState.swift`. Written only
|
||||
/// through `writeSync` and the merge of what linked devices send.
|
||||
@Published internal(set) var syncState = SyncState()
|
||||
@Published var syncState = SyncState()
|
||||
/// Section 17.3: the code this device is showing so a linked device can
|
||||
/// link it, and when it stops being good. Memory only: ten minutes, one
|
||||
/// use.
|
||||
@Published internal(set) var pendingLinkCode: (code: DeviceLinkCode, expires: Date)?
|
||||
@Published var pendingLinkCode: (code: DeviceLinkCode, expires: Date)?
|
||||
/// A numeric-fallback offer held until the person confirms the number here.
|
||||
@Published internal(set) var pendingNumericOffer: PendingLinkOffer?
|
||||
@Published var pendingNumericOffer: PendingLinkOffer?
|
||||
/// What the person is told about changes to the linked set.
|
||||
@Published var linkNotices: [LinkNotice] = []
|
||||
/// Section 17.6: ops written here, waiting to go to the linked devices.
|
||||
|
||||
@@ -393,8 +393,10 @@ final class TodayStore: ObservableObject {
|
||||
/// other traces. The file is public; the picks say where somebody cares
|
||||
/// about, and the next person to use this phone has no business with
|
||||
/// either.
|
||||
static func forgetOnThisPhone(_ store: TodayStore = .shared, defaults: UserDefaults = .standard) {
|
||||
store.forgetEverything()
|
||||
/// `store` is optional because a default of `.shared` is evaluated
|
||||
/// outside the main actor, which Swift 6 refuses.
|
||||
static func forgetOnThisPhone(_ store: TodayStore? = nil, defaults: UserDefaults = .standard) {
|
||||
(store ?? .shared).forgetEverything()
|
||||
defaults.removeObject(forKey: TodayPlaces.key)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ struct BuddyListView: View {
|
||||
// Small, and first: it is the least-used of the three, so it
|
||||
// sits furthest from the thumb rather than displacing the add
|
||||
// button people reach for.
|
||||
MiniWallet()
|
||||
if !WalletAvailability.hidden { MiniWallet() }
|
||||
// The explicit way in for people who don't think to type into
|
||||
// a SEARCH box to add somebody.
|
||||
Button {
|
||||
|
||||
@@ -158,9 +158,13 @@ struct MainTabView: View {
|
||||
.init(
|
||||
id: 5, title: String(localized: "Files"), symbol: "folder.fill",
|
||||
identifier: "files"),
|
||||
.init(
|
||||
id: 6, title: String(localized: "Wallet"), symbol: "wallet.bifold.fill",
|
||||
identifier: "wallet"),
|
||||
// App Store 3.1.5 allows wallets only on organization accounts.
|
||||
// This account is an individual one, so the iOS build has none.
|
||||
WalletAvailability.hidden
|
||||
? nil
|
||||
: .init(
|
||||
id: 6, title: String(localized: "Wallet"), symbol: "wallet.bifold.fill",
|
||||
identifier: "wallet"),
|
||||
.init(
|
||||
id: 4, title: String(localized: "Account"),
|
||||
symbol: "person.crop.circle.fill", badge: unreadAlerts,
|
||||
@@ -209,7 +213,7 @@ struct MainTabView: View {
|
||||
.padding(Theme.Kit.margin)
|
||||
}
|
||||
case 5: FilesView()
|
||||
case 6: WalletScreen()
|
||||
case 6 where !WalletAvailability.hidden: WalletScreen()
|
||||
// Checked here as well as in the bar, so a tab chosen before
|
||||
// supervision was switched on cannot still show it.
|
||||
case 7 where !ParentalControls.todayHidden:
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
import SwiftUI
|
||||
|
||||
/// Off in the App Store build. Guideline 3.1.5 allows crypto wallets only
|
||||
/// from developers enrolled as an organization, and this account is not.
|
||||
enum WalletAvailability {
|
||||
static let hidden = true
|
||||
}
|
||||
|
||||
/// The wallet, from anywhere.
|
||||
struct MiniWallet: View {
|
||||
@EnvironmentObject private var environment: AppEnvironment
|
||||
|
||||
@@ -69,7 +69,9 @@ struct PrivacySettingsView: View {
|
||||
Section {
|
||||
Toggle("Messages", isOn: $passwordForMessages)
|
||||
Toggle("Files", isOn: $passwordForFiles)
|
||||
Toggle("Wallet", isOn: $passwordForWallet)
|
||||
if !WalletAvailability.hidden {
|
||||
Toggle("Wallet", isOn: $passwordForWallet)
|
||||
}
|
||||
} header: {
|
||||
Text("Also ask for your password")
|
||||
} footer: {
|
||||
|
||||
@@ -52,7 +52,9 @@ final class AppStoreShotsUITests: XCTestCase {
|
||||
|
||||
let app = XCUIApplication.underTest()
|
||||
app.launchArguments = ["-FNMSGResetState"]
|
||||
if !haveAccount {
|
||||
// A test launch defaults to a dead loopback address so no suite
|
||||
// reaches production by accident. The store set names its relay.
|
||||
if !signUpRelay.isEmpty {
|
||||
app.launchArguments += ["-FNMSGServer", signUpRelay]
|
||||
}
|
||||
app.launch()
|
||||
@@ -76,7 +78,7 @@ final class AppStoreShotsUITests: XCTestCase {
|
||||
for (tab, name) in [
|
||||
("home", "02-home"), ("messages", "03-messages"),
|
||||
("calls", "04-calls"), ("files", "05-files"),
|
||||
("wallet", "06-wallet"), ("account", "07-account"),
|
||||
("account", "07-account"),
|
||||
] {
|
||||
if openTab(app, tab) { shot(app, name) }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user