Skip to content

Commit 562f0db

Browse files
committed
Port PR #627 onto post-storyboard SwiftUI menu
Port of debug-log-default-on-with-share-notice (PR #627) onto the integration branch where MoreMenuViewController.swift no longer exists (removed by PR #608). The Share Logs flow lives in MoreMenuView.swift now, so the notice prompt and ShareNotice file writer are wired there instead. Migration step renamed from 8 to 9 because step 8 is already taken by the timeInRangeMode migration in this branch.
1 parent d1eb6c0 commit 562f0db

6 files changed

Lines changed: 109 additions & 2 deletions

File tree

LoopFollow.xcodeproj/project.pbxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@
6969
6589CC6D2E9E7D1600BB18FE /* CalendarSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6589CC582E9E7D1600BB18FE /* CalendarSettingsView.swift */; };
7070
6589CC6E2E9E7D1600BB18FE /* SettingsMenuView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6589CC5F2E9E7D1600BB18FE /* SettingsMenuView.swift */; };
7171
6589CC6F2E9E7D1600BB18FE /* AdvancedSettingsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6589CC572E9E7D1600BB18FE /* AdvancedSettingsViewModel.swift */; };
72+
6589CC712E9E7D1600BB18FE /* ShareLogNoticeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6589CC702E9E7D1600BB18FE /* ShareLogNoticeView.swift */; };
7273
6589CC712E9E814F00BB18FE /* AlarmSelectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6589CC702E9E814F00BB18FE /* AlarmSelectionView.swift */; };
7374
6589CC752E9EAFB700BB18FE /* SettingsMigrationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6589CC742E9EAFB700BB18FE /* SettingsMigrationManager.swift */; };
7475
65A100012F5AA00000AA1001 /* UnitsSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65A100002F5AA00000AA1001 /* UnitsSettingsView.swift */; };
@@ -556,6 +557,7 @@
556557
6589CC5E2E9E7D1600BB18FE /* GraphSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GraphSettingsView.swift; sourceTree = "<group>"; };
557558
6589CC5F2E9E7D1600BB18FE /* SettingsMenuView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsMenuView.swift; sourceTree = "<group>"; };
558559
6589CC602E9E7D1600BB18FE /* TabCustomizationModal.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabCustomizationModal.swift; sourceTree = "<group>"; };
560+
6589CC702E9E7D1600BB18FE /* ShareLogNoticeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareLogNoticeView.swift; sourceTree = "<group>"; };
559561
6589CC702E9E814F00BB18FE /* AlarmSelectionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlarmSelectionView.swift; sourceTree = "<group>"; };
560562
6589CC742E9EAFB700BB18FE /* SettingsMigrationManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsMigrationManager.swift; sourceTree = "<group>"; };
561563
65A100002F5AA00000AA1001 /* UnitsSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnitsSettingsView.swift; sourceTree = "<group>"; };
@@ -1052,6 +1054,7 @@
10521054
6589CC5E2E9E7D1600BB18FE /* GraphSettingsView.swift */,
10531055
657F98172F043D8100F732BD /* HomeContentView.swift */,
10541056
6589CC5F2E9E7D1600BB18FE /* SettingsMenuView.swift */,
1057+
6589CC702E9E7D1600BB18FE /* ShareLogNoticeView.swift */,
10551058
65A100002F5AA00000AA1001 /* UnitsSettingsView.swift */,
10561059
65A100022F5AA00000AA1002 /* UnitsConfigurationView.swift */,
10571060
6589CC602E9E7D1600BB18FE /* TabCustomizationModal.swift */,
@@ -2421,6 +2424,7 @@
24212424
65A100032F5AA00000AA1002 /* UnitsConfigurationView.swift in Sources */,
24222425
657F98182F043D8100F732BD /* HomeContentView.swift in Sources */,
24232426
6589CC6F2E9E7D1600BB18FE /* AdvancedSettingsViewModel.swift in Sources */,
2427+
6589CC712E9E7D1600BB18FE /* ShareLogNoticeView.swift in Sources */,
24242428
DD493ADF2ACF22BB009A6922 /* SAge.swift in Sources */,
24252429
DDC6CA3F2DD7C6340060EE25 /* TemporaryAlarmEditor.swift in Sources */,
24262430
DDF699992C5AA3060058A8D9 /* TempTargetPresetManager.swift in Sources */,
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// LoopFollow
2+
// ShareLogNoticeView.swift
3+
4+
import SwiftUI
5+
6+
struct ShareLogNoticeView: View {
7+
@State private var noticeText: String = ""
8+
let onCancel: () -> Void
9+
let onShare: (String) -> Void
10+
11+
var body: some View {
12+
NavigationView {
13+
Form {
14+
Section {
15+
Text("Thanks for sharing these logs to help us find the problem. Please describe it in as much detail as possible — what time did it happen, what did you do, and what did you expect to happen that didn't?")
16+
.font(.callout)
17+
.foregroundColor(.secondary)
18+
}
19+
20+
Section(header: Text("Description")) {
21+
TextEditor(text: $noticeText)
22+
.frame(minHeight: 180)
23+
}
24+
}
25+
.preferredColorScheme(Storage.shared.appearanceMode.value.colorScheme)
26+
.navigationBarTitle("Share Logs", displayMode: .inline)
27+
.toolbar {
28+
ToolbarItem(placement: .cancellationAction) {
29+
Button("Cancel", action: onCancel)
30+
}
31+
ToolbarItem(placement: .confirmationAction) {
32+
Button("Share") { onShare(noticeText) }
33+
}
34+
}
35+
}
36+
}
37+
}

LoopFollow/Storage/Storage+Migrate.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,13 @@ extension Storage {
4545
// else: default "TIR" is already set
4646
}
4747

48+
func migrateStep9() {
49+
// Default for debugLogLevel changed from false to true so users ship useful
50+
// logs when they report a problem. Force-enable for existing users.
51+
LogManager.shared.log(category: .general, message: "Running migrateStep9 — enabling debug log level")
52+
debugLogLevel.value = true
53+
}
54+
4855
func migrateStep7() {
4956
// Cancel notifications scheduled with old hardcoded identifiers.
5057
// Replaced with bundle-ID-scoped identifiers for multi-instance support.

LoopFollow/Storage/Storage.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ class Storage {
3939

4040
var selectedBLEDevice = StorageValue<BLEDevice?>(key: "selectedBLEDevice", defaultValue: nil)
4141

42-
var debugLogLevel = StorageValue<Bool>(key: "debugLogLevel", defaultValue: false)
42+
var debugLogLevel = StorageValue<Bool>(key: "debugLogLevel", defaultValue: true)
4343

4444
var contactTrend = StorageValue<ContactIncludeOption>(key: "contactTrend", defaultValue: .off)
4545
var contactDelta = StorageValue<ContactIncludeOption>(key: "contactDelta", defaultValue: .off)

LoopFollow/ViewControllers/MainViewController.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -663,6 +663,11 @@ class MainViewController: UIViewController, ChartViewDelegate, UNUserNotificatio
663663
Storage.shared.migrateStep8()
664664
Storage.shared.migrationStep.value = 8
665665
}
666+
667+
if Storage.shared.migrationStep.value < 9 {
668+
Storage.shared.migrateStep9()
669+
Storage.shared.migrationStep.value = 9
670+
}
666671
}
667672

668673
@objc func appDidBecomeActive() {

LoopFollow/ViewControllers/MoreMenuView.swift

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,10 +177,64 @@ struct MoreMenuView: View {
177177
showAlert = true
178178
return
179179
}
180-
let avc = UIActivityViewController(activityItems: files, applicationActivities: nil)
180+
181+
let noticeView = ShareLogNoticeView(
182+
onCancel: {
183+
UIApplication.shared.topMost?.dismiss(animated: true)
184+
},
185+
onShare: { noticeText in
186+
UIApplication.shared.topMost?.dismiss(animated: true) {
187+
presentLogShareSheet(noticeText: noticeText, logFiles: files)
188+
}
189+
}
190+
)
191+
let host = UIHostingController(rootView: noticeView)
192+
host.overrideUserInterfaceStyle = Storage.shared.appearanceMode.value.userInterfaceStyle
193+
host.modalPresentationStyle = .formSheet
194+
UIApplication.shared.topMost?.present(host, animated: true)
195+
}
196+
197+
private func presentLogShareSheet(noticeText: String, logFiles: [URL]) {
198+
var items: [Any] = logFiles
199+
if let noticeURL = writeShareNoticeFile(text: noticeText) {
200+
items.insert(noticeURL, at: 0)
201+
}
202+
let avc = UIActivityViewController(activityItems: items, applicationActivities: nil)
181203
UIApplication.shared.topMost?.present(avc, animated: true)
182204
}
183205

206+
private func writeShareNoticeFile(text: String) -> URL? {
207+
let formatter = DateFormatter()
208+
formatter.dateFormat = "yyyy-MM-dd_HHmm"
209+
let timestamp = formatter.string(from: Date())
210+
211+
let version = AppVersionManager().version()
212+
let branchAndSha = BuildDetails.default.branchAndSha
213+
214+
let body = text.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
215+
? "(no description provided)"
216+
: text
217+
218+
let contents = """
219+
LoopFollow Log Share Notice
220+
Date: \(ISO8601DateFormatter().string(from: Date()))
221+
App version: \(version) (\(branchAndSha))
222+
223+
User description:
224+
\(body)
225+
"""
226+
227+
let url = FileManager.default.temporaryDirectory
228+
.appendingPathComponent("ShareNotice_\(timestamp).txt")
229+
do {
230+
try contents.write(to: url, atomically: true, encoding: .utf8)
231+
return url
232+
} catch {
233+
LogManager.shared.log(category: .general, message: "Failed to write share notice file: \(error)")
234+
return nil
235+
}
236+
}
237+
184238
private func fetchVersionInfo() async {
185239
let mgr = AppVersionManager()
186240
let (latest, newer, blacklisted) = await mgr.checkForNewVersionAsync()

0 commit comments

Comments
 (0)