Подавление уведомлений в открытом чате, ускорение переходов между экранами, инициалы на экране разблокировки, плавный keyboard offset

This commit is contained in:
2026-03-13 00:37:36 +05:00
parent c7bea82c3a
commit 7dbddb27a6
4 changed files with 14 additions and 11 deletions

View File

@@ -288,7 +288,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0.10;
MARKETING_VERSION = 1.1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.rosetta.dev;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
@@ -327,7 +327,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0.10;
MARKETING_VERSION = 1.1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.rosetta.dev;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";

View File

@@ -68,7 +68,7 @@ struct AuthCoordinator: View {
.ignoresSafeArea()
.opacity(fadeOverlay ? 1 : 0)
.allowsHitTesting(fadeOverlay)
.animation(.easeInOut(duration: 0.08), value: fadeOverlay)
.animation(.easeInOut(duration: 0.035), value: fadeOverlay)
}
.overlay(alignment: .leading) {
if canSwipeBack {
@@ -174,9 +174,9 @@ private extension AuthCoordinator {
navigationDirection = .forward
fadeOverlay = true
Task { @MainActor in
try? await Task.sleep(nanoseconds: 80_000_000)
try? await Task.sleep(nanoseconds: 35_000_000)
currentScreen = screen
try? await Task.sleep(nanoseconds: 20_000_000)
try? await Task.sleep(nanoseconds: 10_000_000)
fadeOverlay = false
}
}

View File

@@ -119,19 +119,22 @@ struct ChatDetailView: View {
.toolbar(.hidden, for: .tabBar)
.task {
isViewActive = true
// Suppress notifications & clear badge immediately (no 600ms delay).
// setDialogActive only touches MessageRepository.activeDialogs (Set),
// does NOT mutate DialogRepository, so ForEach won't rebuild.
MessageRepository.shared.setDialogActive(route.publicKey, isActive: true)
clearDeliveredNotifications(for: route.publicKey)
// Reset idle timer user is actively viewing a chat.
SessionManager.shared.recordUserInteraction()
// Request user info (non-mutating, won't trigger list rebuild)
requestUserInfoIfNeeded()
// Delay ALL dialog mutations to let navigation transition complete.
// Delay DialogRepository mutations to let navigation transition complete.
// Without this, DialogRepository update rebuilds ChatListView's ForEach
// mid-navigation, recreating the NavigationLink and canceling the push.
try? await Task.sleep(for: .milliseconds(600))
guard isViewActive else { return }
activateDialog()
markDialogAsRead()
// Clear delivered notifications from this sender
clearDeliveredNotifications(for: route.publicKey)
// Subscribe to opponent's online status (Android parity) only after settled
SessionManager.shared.subscribeToOnlineStatus(publicKey: route.publicKey)
// Desktop parity: force-refresh user info (incl. online status) on chat open.

View File

@@ -164,7 +164,7 @@ struct RosettaApp: App {
.ignoresSafeArea()
.opacity(transitionOverlay ? 1 : 0)
.allowsHitTesting(transitionOverlay)
.animation(.easeInOut(duration: 0.08), value: transitionOverlay)
.animation(.easeInOut(duration: 0.035), value: transitionOverlay)
}
.preferredColorScheme(.dark)
.onAppear {
@@ -228,9 +228,9 @@ struct RosettaApp: App {
guard !transitionOverlay else { return }
transitionOverlay = true
Task { @MainActor in
try? await Task.sleep(nanoseconds: 80_000_000) // wait for overlay fade-in
try? await Task.sleep(nanoseconds: 35_000_000) // wait for overlay fade-in
appState = newState
try? await Task.sleep(nanoseconds: 20_000_000) // brief settle
try? await Task.sleep(nanoseconds: 10_000_000) // brief settle
transitionOverlay = false
}
}