diff --git a/.gitignore b/.gitignore index b89a18f..d6b010b 100644 --- a/.gitignore +++ b/.gitignore @@ -64,3 +64,6 @@ playground.xcworkspace # Icon? Icon? + +# Project +project.pbxproj diff --git a/freewrite.xcodeproj/project.pbxproj b/freewrite.xcodeproj/project.pbxproj index b4bede5..e64e6d4 100644 --- a/freewrite.xcodeproj/project.pbxproj +++ b/freewrite.xcodeproj/project.pbxproj @@ -398,11 +398,11 @@ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = YES; CODE_SIGN_ENTITLEMENTS = freewrite/freewrite.entitlements; - "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "-"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_ASSET_PATHS = "\"freewrite/Preview Content\""; - DEVELOPMENT_TEAM = 2UDAY4J48G; + DEVELOPMENT_TEAM = ""; ENABLE_HARDENED_RUNTIME = YES; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; @@ -440,11 +440,11 @@ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = YES; CODE_SIGN_ENTITLEMENTS = freewrite/freewrite.entitlements; - "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "-"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_ASSET_PATHS = "\"freewrite/Preview Content\""; - DEVELOPMENT_TEAM = 2UDAY4J48G; + DEVELOPMENT_TEAM = ""; ENABLE_HARDENED_RUNTIME = YES; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; diff --git a/freewrite/ContentView.swift b/freewrite/ContentView.swift index cb973af..384854e 100644 --- a/freewrite/ContentView.swift +++ b/freewrite/ContentView.swift @@ -85,6 +85,8 @@ struct ContentView: View { @State private var colorScheme: ColorScheme = .light // Add state for color scheme @State private var isHoveringThemeToggle = false // Add state for theme toggle hover @State private var didCopyPrompt: Bool = false // Add state for copy prompt feedback + @State private var strictMode = false // Add state for strict mode + @State private var isHoveringStrictMode = false // Add state for strict mode hover let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect() let entryHeight: CGFloat = 40 @@ -157,6 +159,19 @@ struct ContentView: View { _colorScheme = State(initialValue: savedScheme == "dark" ? .dark : .light) } + // Setup key event monitor for strict mode + private func setupStrictModeKeyMonitor() { + NSEvent.addLocalMonitorForEvents(matching: .keyDown) { event in + // Check if strict mode is enabled and the key is backspace (keyCode 51) + if strictMode && event.keyCode == 51 { + // Block the backspace key by returning nil + return nil + } + // Allow all other key events to pass through + return event + } + } + // Modify getDocumentsDirectory to use cached value private func getDocumentsDirectory() -> URL { return documentsDirectory @@ -382,8 +397,9 @@ struct ContentView: View { return colorScheme == .light ? Color.primary : Color.white } + @State private var viewHeight: CGFloat = 0 + var body: some View { - let buttonBackground = colorScheme == .light ? Color.white : Color.black let navHeight: CGFloat = 68 let textColor = colorScheme == .light ? Color.gray : Color.gray.opacity(0.8) let textHoverColor = colorScheme == .light ? Color.black : Color.white @@ -394,17 +410,18 @@ struct ContentView: View { Color(colorScheme == .light ? .white : .black) .ignoresSafeArea() - TextEditor(text: Binding( - get: { text }, - set: { newValue in - // Ensure the text always starts with two newlines - if !newValue.hasPrefix("\n\n") { - text = "\n\n" + newValue.trimmingCharacters(in: .newlines) - } else { - text = newValue + + TextEditor(text: Binding( + get: { text }, + set: { newValue in + // Ensure the text always starts with two newlines + if !newValue.hasPrefix("\n\n") { + text = "\n\n" + newValue.trimmingCharacters(in: .newlines) + } else { + text = newValue + } } - } - )) + )) .background(Color(colorScheme == .light ? .white : .black)) .font(.custom(selectedFont, size: fontSize)) .foregroundColor(colorScheme == .light ? Color(red: 0.20, green: 0.20, blue: 0.20) : Color(red: 0.9, green: 0.9, blue: 0.9)) @@ -412,6 +429,8 @@ struct ContentView: View { .scrollIndicators(.never) .lineSpacing(lineHeight) .frame(maxWidth: 650) + + .id("\(selectedFont)-\(fontSize)-\(colorScheme)") .padding(.bottom, bottomNavOpacity > 0 ? navHeight : 0) .ignoresSafeArea() @@ -426,13 +445,20 @@ struct ContentView: View { Text(placeholderText) .font(.custom(selectedFont, size: fontSize)) .foregroundColor(colorScheme == .light ? .gray.opacity(0.5) : .gray.opacity(0.6)) - // .padding(.top, 8) - // .padding(.leading, 8) + // .padding(.top, 8) + // .padding(.leading, 8) .allowsHitTesting(false) .offset(x: 5, y: placeholderOffset) } }, alignment: .topLeading ) + .onGeometryChange(for: CGFloat.self) { proxy in + proxy.size.height + } action: { height in + viewHeight = height + } + .contentMargins(.bottom, viewHeight / 4) + VStack { Spacer() @@ -803,6 +829,30 @@ struct ContentView: View { } } + Text("•") + .foregroundColor(.gray) + + // Strict mode toggle button + Button(action: { + strictMode.toggle() + }) { + Image(systemName: strictMode ? "lock.fill" : "lock.open") + .foregroundColor(strictMode ? + (isHoveringStrictMode ? textHoverColor : .red) : + (isHoveringStrictMode ? textHoverColor : textColor)) + } + .buttonStyle(.plain) + .onHover { hovering in + isHoveringStrictMode = hovering + isHoveringBottomNav = hovering + if hovering { + NSCursor.pointingHand.push() + } else { + NSCursor.pop() + } + } + .help(strictMode ? "Strict mode enabled - backspace disabled" : "Enable strict mode") + Text("•") .foregroundColor(.gray) @@ -1027,6 +1077,7 @@ struct ContentView: View { .onAppear { showingSidebar = false // Hide sidebar by default loadExistingEntries() + setupStrictModeKeyMonitor() } .onChange(of: text) { _ in // Save current entry when text changes @@ -1399,4 +1450,4 @@ extension NSView { #Preview { ContentView() -} \ No newline at end of file +} diff --git a/freewrite/default.md b/freewrite/default.md index 767e6ce..f713c7c 100644 --- a/freewrite/default.md +++ b/freewrite/default.md @@ -35,7 +35,7 @@ That’s it. Some basic rules: -- Again, no backspaces +- Again, no backspaces (click on the padlock to toggle strict mode and really enforce this) - No fixing spelling - Little 5–10s breaks are fine, but try to not stop typing - No need to stay on the topic you started with — let your mind wander