diff --git a/DarockBili Watch App/Bangumi/BangumiDetailView.swift b/DarockBili Watch App/Bangumi/BangumiDetailView.swift index c080bb47d..e372ae0b7 100644 --- a/DarockBili Watch App/Bangumi/BangumiDetailView.swift +++ b/DarockBili Watch App/Bangumi/BangumiDetailView.swift @@ -188,7 +188,7 @@ struct BangumiDetailView: View { .tag(2) .navigationTitle("Bangumi.commnets") } - .navigationTitle("番剧") + .navigationTitle("Bangumi") .navigationBarTitleDisplayMode(.inline) .onAppear { let headers: HTTPHeaders = [ diff --git a/DarockBili Watch App/DarockBiliApp.swift b/DarockBili Watch App/DarockBiliApp.swift index 43b69d29a..0510dba34 100644 --- a/DarockBili Watch App/DarockBiliApp.swift +++ b/DarockBili Watch App/DarockBiliApp.swift @@ -106,6 +106,9 @@ struct DarockBili_Watch_AppApp: App { @WKApplicationDelegateAdaptor(AppDelegate.self) var appDelegate @Environment(\.scenePhase) var scenePhase // Screen Time + @AppStorage("isSleepNotificationOn") var isSleepNotificationOn = false + @AppStorage("notifyHour") var notifyHour = 0 + @AppStorage("notifyMinute") var notifyMinute = 0 @AppStorage("IsScreenTimeEnabled") var isScreenTimeEnabled = true @State var screenTimeCaculateTimer: Timer? = nil @State var isMemoryWarningPresented = false @@ -119,6 +122,8 @@ struct DarockBili_Watch_AppApp: App { @State var systemResourceRefreshTimer: Timer? @State var memoryUsage: Float = 0.0 @State var isShowMemoryUsage = false + @State var currentHour = 0 + @State var currentMinute = 0 var body: some Scene { WindowGroup { if UserDefaults.standard.string(forKey: "NewSignalError") ?? "" != "" { @@ -200,6 +205,19 @@ struct DarockBili_Watch_AppApp: App { timer.invalidate() } } + let timer = Timer(timeInterval: 1, repeats: true) { timer in + currentHour = getCurrentTime().hour + currentMinute = getCurrentTime().minute + } + let sleepTimeCheck = Timer(timeInterval: 60, repeats: true) { timer in + if currentHour == notifyHour && currentMinute == notifyMinute && isSleepNotificationOn { + tipWithText(String(localized: "Sleep.notification"), symbol: "bed.double.fill") + } + } + RunLoop.current.add(timer, forMode: .default) + timer.fire() + RunLoop.current.add(sleepTimeCheck, forMode: .default) + sleepTimeCheck.fire() } .overlay { VStack { diff --git a/DarockBili Watch App/Live/LiveDetailView.swift b/DarockBili Watch App/Live/LiveDetailView.swift index 85671e001..7ff58f7ac 100644 --- a/DarockBili Watch App/Live/LiveDetailView.swift +++ b/DarockBili Watch App/Live/LiveDetailView.swift @@ -116,7 +116,7 @@ struct LiveDetailView: View { .bold() } } - .navigationTitle("直播") + .navigationTitle("Live") .navigationBarTitleDisplayMode(.inline) .sheet(isPresented: $isLivePlayerPresented, content: {LivePlayerView()}) .onAppear { @@ -294,7 +294,7 @@ struct LiveDetailView: View { } HStack { Image(systemName: "clock") - Text("于 \(startTime) 开始") + Text("Live.starting.\(startTime)") Spacer() } .offset(y: publishTimeTextOffset) diff --git a/DarockBili Watch App/Others/AboutView.swift b/DarockBili Watch App/Others/AboutView.swift index 1f6bac16d..102c5dbb5 100644 --- a/DarockBili Watch App/Others/AboutView.swift +++ b/DarockBili Watch App/Others/AboutView.swift @@ -115,7 +115,7 @@ struct AboutCredits: View { if isGenshin { ZStack(alignment: .center) { Color.white - Text("原神") + Text("About.genshin") .font(.system(size: 30, weight: .heavy)) .foregroundColor(.black) .opacity(genshinOverlayTextOpacity) @@ -140,16 +140,16 @@ struct AboutCredits: View { @State var codeInput = "" var body: some View { VStack { - TextField("神秘代码", text: $codeInput) + TextField("About.mystery-code", text: $codeInput) Button(action: { if codeInput == "Genshin" { isGenshin = true dismiss() } else { - codeInput = "输入错误" + codeInput = String(localized: "About.mystery-code.error") } }, label: { - Text("确认") + Text("About.confirm") }) } } diff --git a/DarockBili Watch App/Others/SettingsView.swift b/DarockBili Watch App/Others/SettingsView.swift index f8be7f4e9..d054361da 100644 --- a/DarockBili Watch App/Others/SettingsView.swift +++ b/DarockBili Watch App/Others/SettingsView.swift @@ -91,6 +91,18 @@ struct SettingsView: View { Text("Settings.battery") } }) + NavigationLink(destination: {SleepTimeView().navigationTitle("Settings.sleep")}, label: { + HStack { + ZStack { + Color.cyan + .frame(width: 20, height: 20) + .clipShape(Circle()) + Image(systemName: "bed.double.fill") + .font(.system(size: 12)) + } + Text("Settings.sleep") + } + }) NavigationLink(destination: {FeedbackView().navigationTitle("Settings.feedback")}, label: { HStack { ZStack { @@ -368,20 +380,20 @@ struct ScreenTimeSettingsView: View { Button(role: .destructive, action: { isScreenTimeEnabled = false }, label: { - Text("关闭“屏幕使用时间”") + Text("Screen-time.off") }) } footer: { - Text("将不再记录您的屏幕使用时间, 已记录的数据不会被删除") + Text("Screen-time.description") } } else { Section { Button(action: { isScreenTimeEnabled = true }, label: { - Text("开启屏幕使用时间") + Text("Screen-time.on") }) } footer: { - Text("“屏幕使用时间”会记录您每天使用喵哩喵哩的时间并作出统计") + Text("Screen-time.usage") } } } @@ -454,6 +466,81 @@ struct BatterySettingsView: View { } } +struct SleepTimeView: View { + @AppStorage("isSleepNotificationOn") var isSleepNotificationOn = false + @AppStorage("notifyHour") var notifyHour = 0 + @AppStorage("notifyMinute") var notifyMinute = 0 + @State var currentHour = 0 + @State var currentMinute = 0 + @State var currentSecond = 0 + @State var isEditingTime = false + var body: some View { + List { + Section(content: { + Toggle(isOn: $isSleepNotificationOn, label: { + Text("Sleep") + }) + if isSleepNotificationOn { + Button(action: { + isEditingTime = true + }, label: { + Text("Sleep.edit.\(notifyHour<10 ? "0\(notifyHour)" : "\(notifyHour)").\(notifyMinute<10 ? "0\(notifyMinute)" : "\(notifyMinute)")") + }) + } + }, footer: { + Text("Sleep.discription") + }) + Section { + Text("Sleep.current.\(currentHour<10 ? "0\(currentHour)" : "\(currentHour)").\(currentMinute<10 ? "0\(currentMinute)" : "\(currentMinute)").\(currentSecond<10 ? "0\(currentSecond)" : "\(currentSecond)")") + } + } + .navigationTitle("Sleep") + .onAppear { + let timer = Timer(timeInterval: 0.5, repeats: true) { timer in + currentHour = getCurrentTime().hour + currentMinute = getCurrentTime().minute + currentSecond = getCurrentTime().second + } + RunLoop.current.add(timer, forMode: .default) + timer.fire() + } + .sheet(isPresented: $isEditingTime, content: { + VStack { + Text("Sleep.edit.title") + .bold() + HStack { + Picker("Sleep.edit.hour", selection: $notifyHour) { + ForEach(0..<24) { index in + Text("\(index<10 ? "0\(index)" : "\(index)")").tag(index) + } + } + Text(":") + Picker("Sleep.edit.minute", selection: $notifyMinute) { + ForEach(0..<60) { index in + Text("\(index<10 ? "0\(index)" : "\(index)")").tag(index) + } + } + } + } + }) + } +} + +struct Time { + var hour: Int + var minute: Int + var second: Int +} + +func getCurrentTime() -> Time { + let calendar = Calendar.current + let components = calendar.dateComponents([.hour, .minute, .second], from: Date()) + let currentTime = Time(hour: components.hour ?? 0, minute: components.minute ?? 0, second: components.second ?? 0) + return currentTime +} + + + struct DebugMenuView: View { var body: some View { List { diff --git a/DarockBili Watch App/PersonalCenter/HistoryView.swift b/DarockBili Watch App/PersonalCenter/HistoryView.swift index 168300b3f..0b5348aa5 100644 --- a/DarockBili Watch App/PersonalCenter/HistoryView.swift +++ b/DarockBili Watch App/PersonalCenter/HistoryView.swift @@ -73,7 +73,7 @@ struct HistoryView: View { HStack { Spacer(minLength: 0) Image(systemName: "xmark.bin.fill") - Text("这里空空如也") + Text("History.none") Spacer(minLength: 0) } .padding() diff --git a/DarockBili Watch App/Video/VideoDetailView.swift b/DarockBili Watch App/Video/VideoDetailView.swift index 57f4bf10f..10320dfbb 100644 --- a/DarockBili Watch App/Video/VideoDetailView.swift +++ b/DarockBili Watch App/Video/VideoDetailView.swift @@ -290,7 +290,7 @@ struct VideoDetailView: View { } .accentColor(.white) .animation(.smooth, value: isLoading) - .navigationTitle("视频") + .navigationTitle("Video") .navigationBarTitleDisplayMode(.inline) .onAppear { let headers: HTTPHeaders = [ diff --git a/DarockBili Watch App/Video/VideoDownloadView.swift b/DarockBili Watch App/Video/VideoDownloadView.swift index 34bf3bcf0..ecb488881 100644 --- a/DarockBili Watch App/Video/VideoDownloadView.swift +++ b/DarockBili Watch App/Video/VideoDownloadView.swift @@ -51,7 +51,7 @@ struct VideoDownloadView: View { Section { NavigationLink(destination: {DownloadingListView()}, label: { HStack { - Text("视频下载列表") + Text("Download.title") Spacer() Image(systemName: "chevron.right") .opacity(0.65) diff --git a/Localizable.xcstrings b/Localizable.xcstrings index aa733f39b..3d6c47f03 100644 --- a/Localizable.xcstrings +++ b/Localizable.xcstrings @@ -65,6 +65,22 @@ } } }, + ":" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : ":" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : ":" + } + } + } + }, ".%lld" : { "localizations" : { "en" : { @@ -164,6 +180,23 @@ } } }, + "%lld" : { + "extractionState" : "stale", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "%lld" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "%lld" + } + } + } + }, "%lld / %lld" : { "localizations" : { "en" : { @@ -260,6 +293,22 @@ } } }, + "About.confirm" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Confirm" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "确认" + } + } + } + }, "About.credits" : { "localizations" : { "en" : { @@ -276,6 +325,22 @@ } } }, + "About.genshin" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Genshin" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "原神" + } + } + } + }, "About.meowbili" : { "localizations" : { "en" : { @@ -292,6 +357,38 @@ } } }, + "About.mystery-code" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Mystery Code" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "神秘代码" + } + } + } + }, + "About.mystery-code.error" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Input Error" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "输入错误" + } + } + } + }, "About.open-source" : { "localizations" : { "en" : { @@ -668,6 +765,22 @@ } } }, + "Bangumi" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Bangumi" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "番剧" + } + } + } + }, "Bangumi.comments.select" : { "localizations" : { "en" : { @@ -1113,7 +1226,20 @@ } }, "Dignite" : { - + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "Dignite" + } + } + } }, "Direct-message.failed" : { "localizations" : { @@ -1276,6 +1402,22 @@ } } }, + "Download.title" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Download" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "视频下载列表" + } + } + } + }, "Error" : { "localizations" : { "en" : { @@ -1772,6 +1914,22 @@ } } }, + "History.none" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nothing Here" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "这里空空如也" + } + } + } + }, "Home" : { "localizations" : { "en" : { @@ -1948,6 +2106,38 @@ } } }, + "Live" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Live" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "直播" + } + } + } + }, + "Live.starting.%@" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Started at %@" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "于 %@ 开始" + } + } + } + }, "Login.scan" : { "localizations" : { "en" : { @@ -2398,6 +2588,22 @@ } } }, + "Screen-time.description" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Screen Time will not be recorded any more and recorded datas will be cleared" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "将不再记录您的屏幕使用时间, 已记录的数据不会被删除" + } + } + } + }, "Screen-time.minutes.%lld" : { "localizations" : { "en" : { @@ -2426,6 +2632,54 @@ } } }, + "Screen-time.off" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Turn Off Screen Time" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "关闭“屏幕使用时间”" + } + } + } + }, + "Screen-time.on" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Turn One Screen Time" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "开启“屏幕使用时间”" + } + } + } + }, + "Screen-time.usage" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Screen Time will record and count the time you use MeowBili" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "“屏幕使用时间”会记录并统计您每天使用喵哩喵哩的时间" + } + } + } + }, "Search.%@" : { "localizations" : { "en" : { @@ -2539,7 +2793,20 @@ } }, "Search.type.live" : { - + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Lives" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "直播" + } + } + } }, "Search.type.user" : { "localizations" : { @@ -2797,6 +3064,22 @@ } } }, + "Settings.sleep" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sleep" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "睡眠" + } + } + } + }, "Settings.update" : { "localizations" : { "en" : { @@ -2925,6 +3208,134 @@ } } }, + "Sleep" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sleep Time" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "睡眠时间" + } + } + } + }, + "Sleep.current.%@.%@.%@" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "needs_review", + "value" : "It's %1$@:%2$@:%3$@ now" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "现在是%1$@:%2$@:%3$@" + } + } + } + }, + "Sleep.discription" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sleep Time will notify you too sleep at a specific time" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "“睡眠时间”可以在特定时间内提醒您睡觉" + } + } + } + }, + "Sleep.edit.%@.%@" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Edit Sleep Time %1$@:%2$@" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "编辑睡眠时间 %1$@:%2$@" + } + } + } + }, + "Sleep.edit.hour" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "HOUR" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "小时" + } + } + } + }, + "Sleep.edit.minute" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "MINUTE" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "分钟" + } + } + } + }, + "Sleep.edit.title" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Edit Sleep Time" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "编辑睡眠时间" + } + } + } + }, + "Sleep.notification" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Time to Sleep!" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "该睡觉啦!" + } + } + } + }, "ThreeManager785" : { "localizations" : { "en" : { @@ -3879,12 +4290,28 @@ }, "zh-Hans" : { "stringUnit" : { - "state" : "new", + "state" : "translated", "value" : "v%1$@ Build %2$@" } } } }, + "Video" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Video" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "视频" + } + } + } + }, "Video.action.canceled" : { "localizations" : { "en" : { @@ -4273,22 +4700,20 @@ }, "令枫" : { - - }, - "关闭“屏幕使用时间”" : { - - }, - "动态内容" : { - - }, - "动态评论" : { - - }, - "动态详情" : { - - }, - "原神" : { - + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "令枫" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "令枫" + } + } + } }, "发送动态" : { @@ -4311,57 +4736,6 @@ } } } - }, - "将不再记录您的屏幕使用时间, 已记录的数据不会被删除" : { - - }, - "将作为动态主体" : { - - }, - "小尾巴内容" : { - - }, - "已选择的图片" : { - - }, - "应用" : { - - }, - "开启屏幕使用时间" : { - - }, - "您可以更改默认的小尾巴内容, 如果不想添加小尾巴, 请清空上方文本框内容. 您可以随时在设置中更改此内容" : { - - }, - "番剧" : { - - }, - "直播" : { - - }, - "确认" : { - - }, - "视频" : { - - }, - "视频下载列表" : { - - }, - "神秘代码" : { - - }, - "要使用动态小尾巴吗?" : { - - }, - "这里空空如也" : { - - }, - "选择图片" : { - - }, - "重新载入" : { - } }, "version" : "1.0"