Merge branch 'master' into ios-notifications

This commit is contained in:
Evgeny Poberezkin
2022-06-03 13:40:03 +01:00
8 changed files with 72 additions and 72 deletions

View File

@@ -12,21 +12,22 @@ struct ContentView: View {
@ObservedObject var alertManager = AlertManager.shared
@ObservedObject var callController = CallController.shared
@Binding var doAuthenticate: Bool
@Binding var enteredBackground: Double?
@State private var userAuthorized: Bool?
@State private var laFailed: Bool = false
@Binding var userAuthorized: Bool?
@State private var showChatInfo: Bool = false // TODO comprehensively close modal views on authentication
@AppStorage(DEFAULT_SHOW_LA_NOTICE) private var prefShowLANotice = false
@AppStorage(DEFAULT_LA_NOTICE_SHOWN) private var prefLANoticeShown = false
@AppStorage(DEFAULT_PERFORM_LA) private var prefPerformLA = false
var body: some View {
ZStack {
if userAuthorized == true {
if prefPerformLA && userAuthorized != true {
Button(action: runAuthenticate) { Label("Unlock", systemImage: "lock") }
} else {
if let step = chatModel.onboardingStage {
if case .onboardingComplete = step,
let user = chatModel.currentUser {
chatModel.currentUser != nil {
ZStack(alignment: .top) {
ChatListView(user: user)
ChatListView(showChatInfo: $showChatInfo)
.onAppear {
NtfManager.shared.requestAuthorization(onDeny: {
alertManager.showAlert(notificationAlert())
@@ -47,54 +48,39 @@ struct ContentView: View {
OnboardingView(onboarding: step)
}
}
} else if prefPerformLA && laFailed {
retryAuthView()
}
}
.onChange(of: doAuthenticate) { doAuth in
if doAuth, authenticationExpired() {
runAuthenticate()
}
}
.onAppear { if doAuthenticate { runAuthenticate() } }
.onChange(of: doAuthenticate) { _ in if doAuthenticate { runAuthenticate() } }
.alert(isPresented: $alertManager.presentAlert) { alertManager.alertView! }
}
private func retryAuthView() -> some View {
Button {
laFailed = false
runAuthenticate()
} label: { Label("Retry", systemImage: "arrow.counterclockwise") }
}
private func runAuthenticate() {
if !prefPerformLA {
userAuthorized = true
} else {
chatModel.showChatInfo = false
DispatchQueue.main.async() {
userAuthorized = false
authenticate(reason: NSLocalizedString("Unlock", comment: "authentication reason")) { laResult in
switch (laResult) {
case .success:
userAuthorized = true
case .failed:
laFailed = true
AlertManager.shared.showAlert(laFailedAlert())
case .unavailable:
userAuthorized = true
prefPerformLA = false
AlertManager.shared.showAlert(laUnavailableTurningOffAlert())
}
}
} else if showChatInfo {
showChatInfo = false
DispatchQueue.main.async {
justAuthenticate()
}
} else {
justAuthenticate()
}
}
private func authenticationExpired() -> Bool {
if let enteredBackground = enteredBackground {
return ProcessInfo.processInfo.systemUptime - enteredBackground >= 30
} else {
return true
private func justAuthenticate() {
userAuthorized = false
authenticate(reason: NSLocalizedString("Unlock", comment: "authentication reason")) { laResult in
switch (laResult) {
case .success:
userAuthorized = true
case .failed:
AlertManager.shared.showAlert(laFailedAlert())
case .unavailable:
userAuthorized = true
prefPerformLA = false
AlertManager.shared.showAlert(laUnavailableTurningOffAlert())
}
}
}

View File

@@ -15,7 +15,6 @@ import SimpleXChat
final class ChatModel: ObservableObject {
@Published var onboardingStage: OnboardingStage?
@Published var currentUser: User?
@Published var showChatInfo: Bool = false // TODO comprehensively close modal views on authentication
// list of chat "previews"
@Published var chats: [Chat] = []
// current chat

View File

@@ -25,8 +25,8 @@ struct SimpleXApp: App {
@ObservedObject var alertManager = AlertManager.shared
@Environment(\.scenePhase) var scenePhase
@AppStorage(DEFAULT_PERFORM_LA) private var prefPerformLA = false
@State private var userAuthorized: Bool? = nil
@State private var doAuthenticate: Bool = false
@State private var userAuthorized: Bool?
@State private var doAuthenticate = false
@State private var enteredBackground: Double? = nil
init() {
@@ -39,7 +39,7 @@ struct SimpleXApp: App {
var body: some Scene {
return WindowGroup {
ContentView(doAuthenticate: $doAuthenticate, enteredBackground: $enteredBackground)
ContentView(doAuthenticate: $doAuthenticate, userAuthorized: $userAuthorized)
.environmentObject(chatModel)
.onOpenURL { url in
logger.debug("ContentView.onOpenURL: \(url)")
@@ -56,11 +56,13 @@ struct SimpleXApp: App {
switch (phase) {
case .background:
BGManager.shared.schedule()
if userAuthorized == true {
enteredBackground = ProcessInfo.processInfo.systemUptime
}
doAuthenticate = false
enteredBackground = ProcessInfo.processInfo.systemUptime
machMessenger.stop()
case .active:
doAuthenticate = true
doAuthenticate = authenticationExpired()
machMessenger.start()
default:
break
@@ -68,4 +70,12 @@ struct SimpleXApp: App {
}
}
}
private func authenticationExpired() -> Bool {
if let enteredBackground = enteredBackground {
return ProcessInfo.processInfo.systemUptime - enteredBackground >= 30
} else {
return true
}
}
}

View File

@@ -13,6 +13,7 @@ struct ChatInfoView: View {
@EnvironmentObject var chatModel: ChatModel
@ObservedObject var alertManager = AlertManager.shared
@ObservedObject var chat: Chat
@Binding var showChatInfo: Bool
@State var alert: ChatInfoViewAlert? = nil
@State var deletingContact: Contact?
@@ -99,7 +100,7 @@ struct ChatInfoView: View {
try await apiDeleteChat(type: .direct, id: contact.apiId)
DispatchQueue.main.async {
chatModel.removeChat(contact.id)
chatModel.showChatInfo = false
showChatInfo = false
}
} catch let error {
logger.error("ChatInfoView.deleteContactAlert apiDeleteChat error: \(error.localizedDescription)")
@@ -118,7 +119,7 @@ struct ChatInfoView: View {
Task {
await clearChat(chat)
DispatchQueue.main.async {
chatModel.showChatInfo = false
showChatInfo = false
}
}
},
@@ -130,6 +131,6 @@ struct ChatInfoView: View {
struct ChatInfoView_Previews: PreviewProvider {
static var previews: some View {
@State var showChatInfo = true
return ChatInfoView(chat: Chat(chatInfo: ChatInfo.sampleData.direct, chatItems: []))
return ChatInfoView(chat: Chat(chatInfo: ChatInfo.sampleData.direct, chatItems: []), showChatInfo: $showChatInfo)
}
}

View File

@@ -16,6 +16,7 @@ struct ChatView: View {
@Environment(\.colorScheme) var colorScheme
@AppStorage(DEFAULT_EXPERIMENTAL_CALLS) private var enableCalls = false
@ObservedObject var chat: Chat
@Binding var showChatInfo: Bool
@State private var composeState = ComposeState()
@State private var deletingItem: ChatItem? = nil
@FocusState private var keyboardVisible: Bool
@@ -98,12 +99,12 @@ struct ChatView: View {
}
ToolbarItem(placement: .principal) {
Button {
chatModel.showChatInfo = true
showChatInfo = true
} label: {
ChatInfoToolbar(chat: chat)
}
.sheet(isPresented: $chatModel.showChatInfo) {
ChatInfoView(chat: chat)
.sheet(isPresented: $showChatInfo) {
ChatInfoView(chat: chat, showChatInfo: $showChatInfo)
}
}
ToolbarItem(placement: .navigationBarTrailing) {
@@ -270,7 +271,8 @@ struct ChatView_Previews: PreviewProvider {
ChatItem.getSample(8, .directSnd, .now, "👍👍👍👍"),
ChatItem.getSample(9, .directSnd, .now, "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.")
]
return ChatView(chat: Chat(chatInfo: ChatInfo.sampleData.direct, chatItems: []))
@State var showChatInfo = false
return ChatView(chat: Chat(chatInfo: ChatInfo.sampleData.direct, chatItems: []), showChatInfo: $showChatInfo)
.environmentObject(chatModel)
}
}

View File

@@ -12,6 +12,7 @@ import SimpleXChat
struct ChatListNavLink: View {
@EnvironmentObject var chatModel: ChatModel
@State var chat: Chat
@Binding var showChatInfo: Bool
@State private var showContactRequestDialog = false
var body: some View {
@@ -28,7 +29,7 @@ struct ChatListNavLink: View {
}
private func chatView() -> some View {
ChatView(chat: chat)
ChatView(chat: chat, showChatInfo: $showChatInfo)
.onAppear {
do {
let cInfo = chat.chatInfo
@@ -279,19 +280,20 @@ struct ChatListNavLink: View {
struct ChatListNavLink_Previews: PreviewProvider {
static var previews: some View {
@State var chatId: String? = "@1"
@State var showChatInfo = false
return Group {
ChatListNavLink(chat: Chat(
chatInfo: ChatInfo.sampleData.direct,
chatItems: [ChatItem.getSample(1, .directSnd, .now, "hello")]
))
), showChatInfo: $showChatInfo)
ChatListNavLink(chat: Chat(
chatInfo: ChatInfo.sampleData.direct,
chatItems: [ChatItem.getSample(1, .directSnd, .now, "hello")]
))
), showChatInfo: $showChatInfo)
ChatListNavLink(chat: Chat(
chatInfo: ChatInfo.sampleData.contactRequest,
chatItems: []
))
), showChatInfo: $showChatInfo)
}
.previewLayout(.fixed(width: 360, height: 80))
}

View File

@@ -11,18 +11,17 @@ import SimpleXChat
struct ChatListView: View {
@EnvironmentObject var chatModel: ChatModel
@Binding var showChatInfo: Bool
// not really used in this view
@State private var showSettings = false
@State private var searchText = ""
@AppStorage(DEFAULT_PENDING_CONNECTIONS) private var pendingConnections = true
var user: User
var body: some View {
let v = NavigationView {
List {
ForEach(filteredChats()) { chat in
ChatListNavLink(chat: chat)
ChatListNavLink(chat: chat, showChatInfo: $showChatInfo)
.padding(.trailing, -16)
}
}
@@ -93,10 +92,11 @@ struct ChatListView_Previews: PreviewProvider {
)
]
@State var showChatInfo = false
return Group {
ChatListView(user: User.sampleData)
ChatListView(showChatInfo: $showChatInfo)
.environmentObject(chatModel)
ChatListView(user: User.sampleData)
ChatListView(showChatInfo: $showChatInfo)
.environmentObject(ChatModel())
}
}

View File

@@ -1070,7 +1070,7 @@
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = "SimpleX (iOS).entitlements";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 51;
CURRENT_PROJECT_VERSION = 53;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_BITCODE = NO;
ENABLE_PREVIEWS = YES;
@@ -1093,7 +1093,7 @@
);
"LIBRARY_SEARCH_PATHS[sdk=iphoneos*]" = "$(PROJECT_DIR)/Libraries/ios";
"LIBRARY_SEARCH_PATHS[sdk=iphonesimulator*]" = "$(PROJECT_DIR)/Libraries/sim";
MARKETING_VERSION = 2.2;
MARKETING_VERSION = 2.2.1;
PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.app;
PRODUCT_NAME = SimpleX;
SDKROOT = iphoneos;
@@ -1113,7 +1113,7 @@
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = "SimpleX (iOS).entitlements";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 51;
CURRENT_PROJECT_VERSION = 53;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_BITCODE = NO;
ENABLE_PREVIEWS = YES;
@@ -1136,7 +1136,7 @@
);
"LIBRARY_SEARCH_PATHS[sdk=iphoneos*]" = "$(PROJECT_DIR)/Libraries/ios";
"LIBRARY_SEARCH_PATHS[sdk=iphonesimulator*]" = "$(PROJECT_DIR)/Libraries/sim";
MARKETING_VERSION = 2.2;
MARKETING_VERSION = 2.2.1;
PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.app;
PRODUCT_NAME = SimpleX;
SDKROOT = iphoneos;
@@ -1194,7 +1194,7 @@
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = "SimpleX NSE/SimpleX NSE.entitlements";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 51;
CURRENT_PROJECT_VERSION = 53;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_BITCODE = NO;
GENERATE_INFOPLIST_FILE = YES;
@@ -1215,7 +1215,7 @@
"$(inherited)",
"$(PROJECT_DIR)/Libraries/sim",
);
MARKETING_VERSION = 2.2;
MARKETING_VERSION = 2.2.1;
PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.app.SimpleX-NSE";
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos;
@@ -1233,7 +1233,7 @@
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = "SimpleX NSE/SimpleX NSE.entitlements";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 51;
CURRENT_PROJECT_VERSION = 53;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_BITCODE = NO;
GENERATE_INFOPLIST_FILE = YES;
@@ -1254,7 +1254,7 @@
"$(inherited)",
"$(PROJECT_DIR)/Libraries/sim",
);
MARKETING_VERSION = 2.2;
MARKETING_VERSION = 2.2.1;
PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.app.SimpleX-NSE";
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos;