mirror of
https://github.com/TelegramMessenger/Telegram-iOS.git
synced 2026-07-05 19:28:46 +02:00
Update tgwatch
This commit is contained in:
parent
8f4f463265
commit
045ba10386
7 changed files with 48 additions and 87 deletions
BIN
Telegram/WatchApp/tgwatch Watch App/Assets.xcassets/ChatBG.imageset/ChatBG.png
vendored
Normal file
BIN
Telegram/WatchApp/tgwatch Watch App/Assets.xcassets/ChatBG.imageset/ChatBG.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 69 KiB |
13
Telegram/WatchApp/tgwatch Watch App/Assets.xcassets/ChatBG.imageset/Contents.json
vendored
Normal file
13
Telegram/WatchApp/tgwatch Watch App/Assets.xcassets/ChatBG.imageset/Contents.json
vendored
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "ChatBG.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
|
|
@ -1,9 +1,8 @@
|
|||
import SwiftUI
|
||||
|
||||
/// Resolved colors for a message-bubble surface. Incoming bubbles are a fixed light (white)
|
||||
/// surface with dark content; outgoing are the accent surface with white content. Colors are
|
||||
/// FIXED (non-adaptive) on purpose: watchOS runs this app in permanent dark mode, so `.primary`
|
||||
/// would resolve to white and vanish on the white incoming surface.
|
||||
/// Resolved colors for a message-bubble surface. Both directions use a dark fixed surface
|
||||
/// with white content. Colors are FIXED (non-adaptive) on purpose: watchOS runs this app in
|
||||
/// permanent dark mode.
|
||||
struct BubbleStyle: Equatable {
|
||||
let fill: Color
|
||||
let content: Color
|
||||
|
|
@ -13,15 +12,15 @@ struct BubbleStyle: Equatable {
|
|||
let playIcon: Color
|
||||
|
||||
static let incoming = BubbleStyle(
|
||||
fill: .white,
|
||||
content: .black,
|
||||
secondary: Color.black.opacity(0.5),
|
||||
fill: Color(red: 40 / 255, green: 40 / 255, blue: 40 / 255),
|
||||
content: .white,
|
||||
secondary: Color.white.opacity(0.7),
|
||||
replyBar: .accentColor,
|
||||
playFill: .accentColor,
|
||||
playIcon: .white
|
||||
)
|
||||
static let outgoing = BubbleStyle(
|
||||
fill: .accentColor,
|
||||
fill: Color(red: 19 / 255, green: 44 / 255, blue: 73 / 255),
|
||||
content: .white,
|
||||
secondary: Color.white.opacity(0.7),
|
||||
replyBar: Color.white.opacity(0.7),
|
||||
|
|
|
|||
|
|
@ -1,58 +0,0 @@
|
|||
import SwiftUI
|
||||
|
||||
struct ComposeSheet: View {
|
||||
let initialText: String
|
||||
let onSend: (String) async -> Bool
|
||||
let onDismissWithDraft: (String) async -> Void
|
||||
|
||||
@State private var text: String = ""
|
||||
@State private var sending: Bool = false
|
||||
@FocusState private var focused: Bool
|
||||
@Environment(\.dismiss) private var dismiss
|
||||
|
||||
var body: some View {
|
||||
ScrollView {
|
||||
VStack(spacing: 8) {
|
||||
TextField("Reply…", text: $text, axis: .vertical)
|
||||
.focused($focused)
|
||||
.accessibilityIdentifier("composeField")
|
||||
Button(action: send) {
|
||||
if sending {
|
||||
ProgressView()
|
||||
} else {
|
||||
Label("Send", systemImage: "paperplane.fill")
|
||||
}
|
||||
}
|
||||
.buttonStyle(.borderedProminent)
|
||||
.disabled(sending || text.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty)
|
||||
.accessibilityIdentifier("composeSend")
|
||||
}
|
||||
.padding(8)
|
||||
}
|
||||
.task {
|
||||
text = initialText
|
||||
focused = true
|
||||
}
|
||||
.onDisappear {
|
||||
// If we're sending, the dismiss came from send() — skip the draft write.
|
||||
// The send call has clearDraft: true server-side, so the draft is already cleared.
|
||||
guard !sending else { return }
|
||||
let snapshot = text
|
||||
Task { await onDismissWithDraft(snapshot) }
|
||||
}
|
||||
}
|
||||
|
||||
private func send() {
|
||||
let snapshot = text.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
guard !snapshot.isEmpty else { return }
|
||||
sending = true
|
||||
Task {
|
||||
let success = await onSend(snapshot)
|
||||
if success {
|
||||
dismiss()
|
||||
} else {
|
||||
sending = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -16,7 +16,6 @@ struct MessageListView: View {
|
|||
@State private var presentedVideo: VideoVisual?
|
||||
@State private var presentedVideoNote: VideoNoteVisual?
|
||||
@State private var presentedPoll: PollVoteTarget?
|
||||
@State private var showCompose: Bool = false
|
||||
@State private var showAttachment: Bool = false
|
||||
@State private var stickerPickerStore: StickerPickerStore?
|
||||
// True when the user is parked within slop of the bottom edge. Updated only on
|
||||
|
|
@ -79,18 +78,6 @@ struct MessageListView: View {
|
|||
)
|
||||
}
|
||||
}
|
||||
.sheet(isPresented: $showCompose) {
|
||||
if let store {
|
||||
ComposeSheet(
|
||||
initialText: store.draftText,
|
||||
onSend: { text in
|
||||
await store.sendText(text)
|
||||
return store.lastSendError == nil
|
||||
},
|
||||
onDismissWithDraft: { text in await store.saveDraft(text) }
|
||||
)
|
||||
}
|
||||
}
|
||||
.sheet(isPresented: $showAttachment) {
|
||||
if let store {
|
||||
AttachmentSheet(
|
||||
|
|
@ -243,7 +230,9 @@ struct MessageListView: View {
|
|||
if row.canSend {
|
||||
ReplyBar(
|
||||
onAttachTap: { showAttachment = true },
|
||||
onTextTap: { showCompose = true }
|
||||
onSend: { snapshot in
|
||||
Task { await store.sendText(snapshot) }
|
||||
}
|
||||
)
|
||||
.id("composeAnchor")
|
||||
.padding(.top, 8)
|
||||
|
|
@ -261,6 +250,14 @@ struct MessageListView: View {
|
|||
}
|
||||
.ignoresSafeArea(edges: .bottom)
|
||||
.defaultScrollAnchor(.bottom)
|
||||
.scrollContentBackground(.hidden)
|
||||
.background {
|
||||
Image("ChatBG")
|
||||
.resizable()
|
||||
.aspectRatio(contentMode: .fill)
|
||||
.clipped()
|
||||
.ignoresSafeArea()
|
||||
}
|
||||
.environment(store)
|
||||
.task {
|
||||
// Default branch only appears once `loadState == .loaded`
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import SwiftUI
|
|||
|
||||
struct ReplyBar: View {
|
||||
let onAttachTap: () -> Void
|
||||
let onTextTap: () -> Void
|
||||
let onSend: (String) -> Void
|
||||
|
||||
// Circular "+" button and reply-field capsule share a single pill
|
||||
// diameter so they line up vertically and visually mirror the
|
||||
|
|
@ -25,17 +25,31 @@ struct ReplyBar: View {
|
|||
.padding(.leading, 11)
|
||||
.accessibilityIdentifier("replyBarAttach")
|
||||
|
||||
Button(action: onTextTap) {
|
||||
// TextFieldLink renders an arbitrary label and, when tapped,
|
||||
// presents the watchOS system text input UI (QuickboardViewService).
|
||||
// It returns the committed string in onSubmit. The label IS our
|
||||
// glassy pill — fully styled, no double-chrome artifacts.
|
||||
//
|
||||
// Limitation: TextFieldLink does not accept an initial value, so
|
||||
// the input UI opens blank every time. Existing server-side drafts
|
||||
// are not visible or editable from the watch under this design —
|
||||
// accepted regression vs. the prior ComposeSheet flow.
|
||||
TextFieldLink(prompt: Text("Reply…")) {
|
||||
HStack(spacing: 0) {
|
||||
Text("Reply…")
|
||||
.font(.caption)
|
||||
.foregroundStyle(.secondary)
|
||||
.lineLimit(1)
|
||||
Spacer(minLength: 0)
|
||||
}
|
||||
.padding(.horizontal, 12)
|
||||
.frame(height: Self.pillHeight)
|
||||
.contentShape(Rectangle())
|
||||
.glassEffect()
|
||||
} onSubmit: { newText in
|
||||
let snapshot = newText.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
guard !snapshot.isEmpty else { return }
|
||||
onSend(snapshot)
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
.layoutPriority(1)
|
||||
|
|
@ -64,7 +78,7 @@ private struct ReplyBarGeometryPreviewHost: View {
|
|||
.padding(.top, 6)
|
||||
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading)
|
||||
|
||||
ReplyBar(onAttachTap: {}, onTextTap: {})
|
||||
ReplyBar(onAttachTap: {}, onSend: { _ in })
|
||||
.padding(.horizontal, 4)
|
||||
.padding(.bottom, 19)
|
||||
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .bottom)
|
||||
|
|
|
|||
|
|
@ -75,7 +75,6 @@
|
|||
A0899809BBC92D1563AC4160 /* ReplyBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7584BF25A84BAD24AB992A79 /* ReplyBar.swift */; };
|
||||
A121DA7622C910B267D69B6E /* PhotoBubbleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0F7533C5A9B419B29727C86 /* PhotoBubbleView.swift */; };
|
||||
A6179A26CB7FB298567682E6 /* DocumentVisual.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF2515F0EDA29D5270610A69 /* DocumentVisual.swift */; };
|
||||
A73233E40B531EA2D4A81B78 /* ComposeSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54149DBDF74BC221A94FB1AD /* ComposeSheet.swift */; };
|
||||
A7967495A54936FE19218DC4 /* ServiceMessageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF393D904BF677AC5721EC7E /* ServiceMessageView.swift */; };
|
||||
A8EF6F72C78B619893C05AFE /* ChatPreview.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3448938C1F69F0D9DE679238 /* ChatPreview.swift */; };
|
||||
AA3F067A7BC4CDA579CFFC39 /* PollVisual.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE4D691106D7EA2FEE35F37F /* PollVisual.swift */; };
|
||||
|
|
@ -149,7 +148,6 @@
|
|||
4DB3C8238D41374CBAC66303 /* EmojiText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiText.swift; sourceTree = "<group>"; };
|
||||
4E049ECC956A583A92C5C7CB /* SecretsValidator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecretsValidator.swift; sourceTree = "<group>"; };
|
||||
53B9831274FA56126E3F5A42 /* LocationSendView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationSendView.swift; sourceTree = "<group>"; };
|
||||
54149DBDF74BC221A94FB1AD /* ComposeSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeSheet.swift; sourceTree = "<group>"; };
|
||||
596AF8BF88C38D2018397A33 /* LocationBubbleView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationBubbleView.swift; sourceTree = "<group>"; };
|
||||
5D3A8FBA5EBDBFDE5AA2FFEC /* QrLoginView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QrLoginView.swift; sourceTree = "<group>"; };
|
||||
5EA750417DF3AD62C7B788F6 /* MessageListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageListView.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -340,7 +338,6 @@
|
|||
3EEAE6237003C5CDA788E928 /* BubbleStyle.swift */,
|
||||
C2C84B842AD08D079BFF08A0 /* ChatHistoryLoader.swift */,
|
||||
182DA99AD90B93DE2FB37A41 /* ChatHistoryStore.swift */,
|
||||
54149DBDF74BC221A94FB1AD /* ComposeSheet.swift */,
|
||||
E855E4C62401AD1CF41D1835 /* DaySeparatorView.swift */,
|
||||
BDBE08BBB88597B10CDF0142 /* DocumentBubbleView.swift */,
|
||||
FF2515F0EDA29D5270610A69 /* DocumentVisual.swift */,
|
||||
|
|
@ -536,7 +533,6 @@
|
|||
E48523AFA2E23409CC0C2C2C /* ChatRow.swift in Sources */,
|
||||
7BF1C89F67290EBAF50900F8 /* ChatRowView.swift in Sources */,
|
||||
04CEF3F9C267D8A7CEC5EC3C /* ClosedView.swift in Sources */,
|
||||
A73233E40B531EA2D4A81B78 /* ComposeSheet.swift in Sources */,
|
||||
EF499261BE49A6B1C7B3B1F4 /* ContentView.swift in Sources */,
|
||||
FD5515DB22C571F4D3E5F5FA /* DaySeparatorView.swift in Sources */,
|
||||
F5596A4EF4D2055B10B4A183 /* DocumentBubbleView.swift in Sources */,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue