├── AppKitIntegration ├── AppKitController.swift └── Info.plist ├── README.md ├── smalltext.xcodeproj ├── project.pbxproj └── project.xcworkspace │ └── contents.xcworkspacedata └── smalltext ├── Assets.xcassets ├── AccentColor.colorset │ └── Contents.json ├── AppIcon.appiconset │ ├── Contents.json │ ├── SmallText-BigSur-1.png │ ├── SmallText-BigSur.png │ └── SmallText-BigSur@0.5x.png └── Contents.json ├── Base.lproj └── LaunchScreen.storyboard ├── Controllers ├── STXAppDelegate.swift ├── STXDocumentBrowserViewController.swift └── STXWindowScene.swift ├── Document Editor ├── STXDocument.swift ├── STXDocumentViewController.swift └── Toolbar Views │ ├── STXColorButton.swift │ ├── STXFontButton.swift │ ├── STXHairlineDividerView.swift │ └── STXVisualEffectView.swift ├── Info.plist ├── InfoPlist.strings ├── Number+Scaling.swift ├── WindowScene.swift └── smalltext.entitlements /AppKitIntegration/AppKitController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppKitController.swift 3 | // AppKitIntegration 4 | // 5 | // Created by Steven Troughton-Smith on 30/01/2021. 6 | // 7 | 8 | import AppKit 9 | 10 | extension NSObject { 11 | @objc func hostWindowForSceneIdentifier(_ identifier:String) -> NSWindow? { 12 | return nil 13 | } 14 | } 15 | 16 | class AppKitController : NSObject { 17 | @objc public func _marzipan_setupWindow(_ note:Notification) { 18 | 19 | NSLog("_marzipan_setupWindow: \(note.userInfo)") 20 | 21 | guard let userInfo = note.userInfo, let sceneIdentifier = userInfo["SceneIdentifier"] as? String else { return } 22 | 23 | prepareWindowForSceneIdentifier(sceneIdentifier) 24 | } 25 | 26 | @objc public func prepareWindowForSceneIdentifier(_ sceneIdentifier:String) { 27 | guard let appDelegate = NSApp.delegate as? NSObject else { return } 28 | 29 | if appDelegate.responds(to: #selector(hostWindowForSceneIdentifier(_:))) { 30 | guard let hostWindow = appDelegate.hostWindowForSceneIdentifier(sceneIdentifier) else { return } 31 | 32 | DispatchQueue.main.asyncAfter(deadline: .now() + 0.0) { 33 | hostWindow.titlebarAppearsTransparent = true 34 | } 35 | } 36 | } 37 | 38 | @objc public func hideWindowForSceneIdentifier(_ sceneIdentifier:String) { 39 | guard let appDelegate = NSApp.delegate as? NSObject else { return } 40 | 41 | if appDelegate.responds(to: #selector(hostWindowForSceneIdentifier(_:))) { 42 | guard let hostWindow = appDelegate.hostWindowForSceneIdentifier(sceneIdentifier) else { return } 43 | 44 | hostWindow.alphaValue = 0 45 | } 46 | } 47 | 48 | @objc public func showWindowForSceneIdentifier(_ sceneIdentifier:String) { 49 | guard let appDelegate = NSApp.delegate as? NSObject else { return } 50 | 51 | if appDelegate.responds(to: #selector(hostWindowForSceneIdentifier(_:))) { 52 | guard let hostWindow = appDelegate.hostWindowForSceneIdentifier(sceneIdentifier) else { return } 53 | 54 | hostWindow.alphaValue = 1 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /AppKitIntegration/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SmallText 2 | 3 | This is a modern reimagining in Catalyst (Mac Idiom) of one of my first projects for Mac, SmallText, from 2000–2001. 4 | 5 | This is just for fun and not expected to work, is not a usable product, and I don't intend on developing it much further. 6 | 7 | ### Screenshots 8 | 9 | ![https://hccdata.s3.us-east-1.amazonaws.com/gh_SmallTextXv3.jpg](https://hccdata.s3.us-east-1.amazonaws.com/gh_SmallTextXv3.jpg "SmallText X, SmallText side-by-side") 10 | 11 | -------------------------------------------------------------------------------- /smalltext.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 52; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | B01D61BD27BA19C6000B349C /* STXHairlineDividerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B01D61BC27BA19C6000B349C /* STXHairlineDividerView.swift */; }; 11 | B04A806E25C38E8200CCC1D8 /* STXVisualEffectView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B04A806D25C38E8200CCC1D8 /* STXVisualEffectView.swift */; }; 12 | B04A807225C38EE600CCC1D8 /* STXColorButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = B04A807125C38EE600CCC1D8 /* STXColorButton.swift */; }; 13 | B0581F2C25C27281000AEF90 /* STXDocumentBrowserViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0581F2B25C27281000AEF90 /* STXDocumentBrowserViewController.swift */; }; 14 | B0581F3225C272C3000AEF90 /* STXDocumentViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0581F3125C272C3000AEF90 /* STXDocumentViewController.swift */; }; 15 | B0581F3625C276C6000AEF90 /* Number+Scaling.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0581F3525C276C6000AEF90 /* Number+Scaling.swift */; }; 16 | B05C9E9525C4BEB8002DE786 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = B05C9E9425C4BEB8002DE786 /* InfoPlist.strings */; }; 17 | B08BC09625C5147100C08C81 /* AppKitIntegration.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = B08BC08625C5143D00C08C81 /* AppKitIntegration.framework */; platformFilter = maccatalyst; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; 18 | B08BC09925C5148200C08C81 /* AppKitController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B08BC09825C5148200C08C81 /* AppKitController.swift */; }; 19 | B09299E625C394F30072E89A /* STXFontButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = B09299E525C394F30072E89A /* STXFontButton.swift */; }; 20 | B0A6BA8425C26B49007F945E /* STXAppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0A6BA8325C26B49007F945E /* STXAppDelegate.swift */; }; 21 | B0A6BA8A25C26B49007F945E /* STXDocument.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0A6BA8925C26B49007F945E /* STXDocument.swift */; }; 22 | B0A6BA8F25C26B4B007F945E /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = B0A6BA8E25C26B4B007F945E /* Assets.xcassets */; }; 23 | B0A6BA9225C26B4B007F945E /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B0A6BA9025C26B4B007F945E /* LaunchScreen.storyboard */; }; 24 | B0A6BA9F25C26BE9007F945E /* STXWindowScene.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0A6BA9E25C26BE9007F945E /* STXWindowScene.swift */; }; 25 | /* End PBXBuildFile section */ 26 | 27 | /* Begin PBXContainerItemProxy section */ 28 | B08BC09025C5144B00C08C81 /* PBXContainerItemProxy */ = { 29 | isa = PBXContainerItemProxy; 30 | containerPortal = B0A6BA7825C26B49007F945E /* Project object */; 31 | proxyType = 1; 32 | remoteGlobalIDString = B08BC08525C5143D00C08C81; 33 | remoteInfo = AppKitIntegration; 34 | }; 35 | /* End PBXContainerItemProxy section */ 36 | 37 | /* Begin PBXCopyFilesBuildPhase section */ 38 | B08BC09525C5146700C08C81 /* CopyFiles */ = { 39 | isa = PBXCopyFilesBuildPhase; 40 | buildActionMask = 2147483647; 41 | dstPath = ""; 42 | dstSubfolderSpec = 10; 43 | files = ( 44 | B08BC09625C5147100C08C81 /* AppKitIntegration.framework in CopyFiles */, 45 | ); 46 | runOnlyForDeploymentPostprocessing = 0; 47 | }; 48 | /* End PBXCopyFilesBuildPhase section */ 49 | 50 | /* Begin PBXFileReference section */ 51 | B01D61BC27BA19C6000B349C /* STXHairlineDividerView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = STXHairlineDividerView.swift; sourceTree = ""; }; 52 | B04A806D25C38E8200CCC1D8 /* STXVisualEffectView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = STXVisualEffectView.swift; sourceTree = ""; }; 53 | B04A807125C38EE600CCC1D8 /* STXColorButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STXColorButton.swift; sourceTree = ""; }; 54 | B0581F2B25C27281000AEF90 /* STXDocumentBrowserViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = STXDocumentBrowserViewController.swift; sourceTree = ""; }; 55 | B0581F3125C272C3000AEF90 /* STXDocumentViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STXDocumentViewController.swift; sourceTree = ""; }; 56 | B0581F3525C276C6000AEF90 /* Number+Scaling.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Number+Scaling.swift"; sourceTree = ""; }; 57 | B05C9E9425C4BEB8002DE786 /* InfoPlist.strings */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; path = InfoPlist.strings; sourceTree = ""; }; 58 | B05C9E9725C4C1A1002DE786 /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; 59 | B08BC08625C5143D00C08C81 /* AppKitIntegration.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = AppKitIntegration.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 60 | B08BC08925C5143D00C08C81 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 61 | B08BC09825C5148200C08C81 /* AppKitController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppKitController.swift; sourceTree = ""; }; 62 | B09299E525C394F30072E89A /* STXFontButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STXFontButton.swift; sourceTree = ""; }; 63 | B0A6BA8025C26B49007F945E /* smalltext.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = smalltext.app; sourceTree = BUILT_PRODUCTS_DIR; }; 64 | B0A6BA8325C26B49007F945E /* STXAppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STXAppDelegate.swift; sourceTree = ""; }; 65 | B0A6BA8925C26B49007F945E /* STXDocument.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STXDocument.swift; sourceTree = ""; }; 66 | B0A6BA8E25C26B4B007F945E /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 67 | B0A6BA9125C26B4B007F945E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 68 | B0A6BA9325C26B4B007F945E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 69 | B0A6BA9B25C26B7A007F945E /* smalltext.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = smalltext.entitlements; sourceTree = ""; }; 70 | B0A6BA9E25C26BE9007F945E /* STXWindowScene.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = STXWindowScene.swift; sourceTree = ""; }; 71 | /* End PBXFileReference section */ 72 | 73 | /* Begin PBXFrameworksBuildPhase section */ 74 | B08BC08325C5143D00C08C81 /* Frameworks */ = { 75 | isa = PBXFrameworksBuildPhase; 76 | buildActionMask = 2147483647; 77 | files = ( 78 | ); 79 | runOnlyForDeploymentPostprocessing = 0; 80 | }; 81 | B0A6BA7D25C26B49007F945E /* Frameworks */ = { 82 | isa = PBXFrameworksBuildPhase; 83 | buildActionMask = 2147483647; 84 | files = ( 85 | ); 86 | runOnlyForDeploymentPostprocessing = 0; 87 | }; 88 | /* End PBXFrameworksBuildPhase section */ 89 | 90 | /* Begin PBXGroup section */ 91 | B05C9E9B25C4C2DA002DE786 /* Toolbar Views */ = { 92 | isa = PBXGroup; 93 | children = ( 94 | B01D61BC27BA19C6000B349C /* STXHairlineDividerView.swift */, 95 | B04A806D25C38E8200CCC1D8 /* STXVisualEffectView.swift */, 96 | B04A807125C38EE600CCC1D8 /* STXColorButton.swift */, 97 | B09299E525C394F30072E89A /* STXFontButton.swift */, 98 | ); 99 | path = "Toolbar Views"; 100 | sourceTree = ""; 101 | }; 102 | B05C9E9D25C4C2F4002DE786 /* Document Editor */ = { 103 | isa = PBXGroup; 104 | children = ( 105 | B0A6BA8925C26B49007F945E /* STXDocument.swift */, 106 | B0581F3125C272C3000AEF90 /* STXDocumentViewController.swift */, 107 | B05C9E9B25C4C2DA002DE786 /* Toolbar Views */, 108 | ); 109 | path = "Document Editor"; 110 | sourceTree = ""; 111 | }; 112 | B05C9E9F25C4C301002DE786 /* Controllers */ = { 113 | isa = PBXGroup; 114 | children = ( 115 | B0A6BA8325C26B49007F945E /* STXAppDelegate.swift */, 116 | B0A6BA9E25C26BE9007F945E /* STXWindowScene.swift */, 117 | B0581F2B25C27281000AEF90 /* STXDocumentBrowserViewController.swift */, 118 | ); 119 | path = Controllers; 120 | sourceTree = ""; 121 | }; 122 | B08BC08725C5143D00C08C81 /* AppKitIntegration */ = { 123 | isa = PBXGroup; 124 | children = ( 125 | B08BC09825C5148200C08C81 /* AppKitController.swift */, 126 | B08BC08925C5143D00C08C81 /* Info.plist */, 127 | ); 128 | path = AppKitIntegration; 129 | sourceTree = ""; 130 | }; 131 | B08BC09225C5145000C08C81 /* Frameworks */ = { 132 | isa = PBXGroup; 133 | children = ( 134 | ); 135 | name = Frameworks; 136 | sourceTree = ""; 137 | }; 138 | B0A6BA7725C26B49007F945E = { 139 | isa = PBXGroup; 140 | children = ( 141 | B05C9E9725C4C1A1002DE786 /* README.md */, 142 | B0A6BA8225C26B49007F945E /* smalltext */, 143 | B08BC08725C5143D00C08C81 /* AppKitIntegration */, 144 | B0A6BA8125C26B49007F945E /* Products */, 145 | B08BC09225C5145000C08C81 /* Frameworks */, 146 | ); 147 | sourceTree = ""; 148 | }; 149 | B0A6BA8125C26B49007F945E /* Products */ = { 150 | isa = PBXGroup; 151 | children = ( 152 | B0A6BA8025C26B49007F945E /* smalltext.app */, 153 | B08BC08625C5143D00C08C81 /* AppKitIntegration.framework */, 154 | ); 155 | name = Products; 156 | sourceTree = ""; 157 | }; 158 | B0A6BA8225C26B49007F945E /* smalltext */ = { 159 | isa = PBXGroup; 160 | children = ( 161 | B0A6BA9B25C26B7A007F945E /* smalltext.entitlements */, 162 | B0581F3525C276C6000AEF90 /* Number+Scaling.swift */, 163 | B05C9E9F25C4C301002DE786 /* Controllers */, 164 | B05C9E9D25C4C2F4002DE786 /* Document Editor */, 165 | B0A6BA8E25C26B4B007F945E /* Assets.xcassets */, 166 | B0A6BA9025C26B4B007F945E /* LaunchScreen.storyboard */, 167 | B0A6BA9325C26B4B007F945E /* Info.plist */, 168 | B05C9E9425C4BEB8002DE786 /* InfoPlist.strings */, 169 | ); 170 | path = smalltext; 171 | sourceTree = ""; 172 | }; 173 | /* End PBXGroup section */ 174 | 175 | /* Begin PBXHeadersBuildPhase section */ 176 | B08BC08125C5143D00C08C81 /* Headers */ = { 177 | isa = PBXHeadersBuildPhase; 178 | buildActionMask = 2147483647; 179 | files = ( 180 | ); 181 | runOnlyForDeploymentPostprocessing = 0; 182 | }; 183 | /* End PBXHeadersBuildPhase section */ 184 | 185 | /* Begin PBXNativeTarget section */ 186 | B08BC08525C5143D00C08C81 /* AppKitIntegration */ = { 187 | isa = PBXNativeTarget; 188 | buildConfigurationList = B08BC08D25C5143D00C08C81 /* Build configuration list for PBXNativeTarget "AppKitIntegration" */; 189 | buildPhases = ( 190 | B08BC08125C5143D00C08C81 /* Headers */, 191 | B08BC08225C5143D00C08C81 /* Sources */, 192 | B08BC08325C5143D00C08C81 /* Frameworks */, 193 | B08BC08425C5143D00C08C81 /* Resources */, 194 | ); 195 | buildRules = ( 196 | ); 197 | dependencies = ( 198 | ); 199 | name = AppKitIntegration; 200 | productName = AppKitIntegration; 201 | productReference = B08BC08625C5143D00C08C81 /* AppKitIntegration.framework */; 202 | productType = "com.apple.product-type.framework"; 203 | }; 204 | B0A6BA7F25C26B49007F945E /* smalltext */ = { 205 | isa = PBXNativeTarget; 206 | buildConfigurationList = B0A6BA9625C26B4B007F945E /* Build configuration list for PBXNativeTarget "smalltext" */; 207 | buildPhases = ( 208 | B0A6BA7C25C26B49007F945E /* Sources */, 209 | B0A6BA7D25C26B49007F945E /* Frameworks */, 210 | B0A6BA7E25C26B49007F945E /* Resources */, 211 | B08BC09525C5146700C08C81 /* CopyFiles */, 212 | ); 213 | buildRules = ( 214 | ); 215 | dependencies = ( 216 | B08BC09125C5144B00C08C81 /* PBXTargetDependency */, 217 | ); 218 | name = smalltext; 219 | productName = smalltext; 220 | productReference = B0A6BA8025C26B49007F945E /* smalltext.app */; 221 | productType = "com.apple.product-type.application"; 222 | }; 223 | /* End PBXNativeTarget section */ 224 | 225 | /* Begin PBXProject section */ 226 | B0A6BA7825C26B49007F945E /* Project object */ = { 227 | isa = PBXProject; 228 | attributes = { 229 | CLASSPREFIX = STX; 230 | LastSwiftUpdateCheck = 1240; 231 | LastUpgradeCheck = 1240; 232 | TargetAttributes = { 233 | B08BC08525C5143D00C08C81 = { 234 | CreatedOnToolsVersion = 12.4; 235 | LastSwiftMigration = 1240; 236 | }; 237 | B0A6BA7F25C26B49007F945E = { 238 | CreatedOnToolsVersion = 12.4; 239 | }; 240 | }; 241 | }; 242 | buildConfigurationList = B0A6BA7B25C26B49007F945E /* Build configuration list for PBXProject "smalltext" */; 243 | compatibilityVersion = "Xcode 9.3"; 244 | developmentRegion = en; 245 | hasScannedForEncodings = 0; 246 | knownRegions = ( 247 | en, 248 | Base, 249 | ); 250 | mainGroup = B0A6BA7725C26B49007F945E; 251 | productRefGroup = B0A6BA8125C26B49007F945E /* Products */; 252 | projectDirPath = ""; 253 | projectRoot = ""; 254 | targets = ( 255 | B0A6BA7F25C26B49007F945E /* smalltext */, 256 | B08BC08525C5143D00C08C81 /* AppKitIntegration */, 257 | ); 258 | }; 259 | /* End PBXProject section */ 260 | 261 | /* Begin PBXResourcesBuildPhase section */ 262 | B08BC08425C5143D00C08C81 /* Resources */ = { 263 | isa = PBXResourcesBuildPhase; 264 | buildActionMask = 2147483647; 265 | files = ( 266 | ); 267 | runOnlyForDeploymentPostprocessing = 0; 268 | }; 269 | B0A6BA7E25C26B49007F945E /* Resources */ = { 270 | isa = PBXResourcesBuildPhase; 271 | buildActionMask = 2147483647; 272 | files = ( 273 | B0A6BA9225C26B4B007F945E /* LaunchScreen.storyboard in Resources */, 274 | B05C9E9525C4BEB8002DE786 /* InfoPlist.strings in Resources */, 275 | B0A6BA8F25C26B4B007F945E /* Assets.xcassets in Resources */, 276 | ); 277 | runOnlyForDeploymentPostprocessing = 0; 278 | }; 279 | /* End PBXResourcesBuildPhase section */ 280 | 281 | /* Begin PBXSourcesBuildPhase section */ 282 | B08BC08225C5143D00C08C81 /* Sources */ = { 283 | isa = PBXSourcesBuildPhase; 284 | buildActionMask = 2147483647; 285 | files = ( 286 | B08BC09925C5148200C08C81 /* AppKitController.swift in Sources */, 287 | ); 288 | runOnlyForDeploymentPostprocessing = 0; 289 | }; 290 | B0A6BA7C25C26B49007F945E /* Sources */ = { 291 | isa = PBXSourcesBuildPhase; 292 | buildActionMask = 2147483647; 293 | files = ( 294 | B01D61BD27BA19C6000B349C /* STXHairlineDividerView.swift in Sources */, 295 | B0581F2C25C27281000AEF90 /* STXDocumentBrowserViewController.swift in Sources */, 296 | B0581F3225C272C3000AEF90 /* STXDocumentViewController.swift in Sources */, 297 | B09299E625C394F30072E89A /* STXFontButton.swift in Sources */, 298 | B0A6BA8A25C26B49007F945E /* STXDocument.swift in Sources */, 299 | B04A806E25C38E8200CCC1D8 /* STXVisualEffectView.swift in Sources */, 300 | B0A6BA8425C26B49007F945E /* STXAppDelegate.swift in Sources */, 301 | B04A807225C38EE600CCC1D8 /* STXColorButton.swift in Sources */, 302 | B0A6BA9F25C26BE9007F945E /* STXWindowScene.swift in Sources */, 303 | B0581F3625C276C6000AEF90 /* Number+Scaling.swift in Sources */, 304 | ); 305 | runOnlyForDeploymentPostprocessing = 0; 306 | }; 307 | /* End PBXSourcesBuildPhase section */ 308 | 309 | /* Begin PBXTargetDependency section */ 310 | B08BC09125C5144B00C08C81 /* PBXTargetDependency */ = { 311 | isa = PBXTargetDependency; 312 | platformFilter = maccatalyst; 313 | target = B08BC08525C5143D00C08C81 /* AppKitIntegration */; 314 | targetProxy = B08BC09025C5144B00C08C81 /* PBXContainerItemProxy */; 315 | }; 316 | /* End PBXTargetDependency section */ 317 | 318 | /* Begin PBXVariantGroup section */ 319 | B0A6BA9025C26B4B007F945E /* LaunchScreen.storyboard */ = { 320 | isa = PBXVariantGroup; 321 | children = ( 322 | B0A6BA9125C26B4B007F945E /* Base */, 323 | ); 324 | name = LaunchScreen.storyboard; 325 | sourceTree = ""; 326 | }; 327 | /* End PBXVariantGroup section */ 328 | 329 | /* Begin XCBuildConfiguration section */ 330 | B08BC08B25C5143D00C08C81 /* Debug */ = { 331 | isa = XCBuildConfiguration; 332 | buildSettings = { 333 | CLANG_ENABLE_MODULES = YES; 334 | CODE_SIGN_STYLE = Automatic; 335 | COMBINE_HIDPI_IMAGES = YES; 336 | CURRENT_PROJECT_VERSION = 1; 337 | DEFINES_MODULE = YES; 338 | DEVELOPMENT_TEAM = 2ZDN69KUUV; 339 | DYLIB_COMPATIBILITY_VERSION = 1; 340 | DYLIB_CURRENT_VERSION = 1; 341 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 342 | INFOPLIST_FILE = AppKitIntegration/Info.plist; 343 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 344 | LD_RUNPATH_SEARCH_PATHS = ( 345 | "$(inherited)", 346 | "@executable_path/../Frameworks", 347 | "@loader_path/Frameworks", 348 | ); 349 | MACOSX_DEPLOYMENT_TARGET = 11.1; 350 | PRODUCT_BUNDLE_IDENTIFIER = com.highcaffeinecontent.AppKitIntegration; 351 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; 352 | SDKROOT = macosx; 353 | SKIP_INSTALL = YES; 354 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 355 | SWIFT_VERSION = 5.0; 356 | VERSIONING_SYSTEM = "apple-generic"; 357 | VERSION_INFO_PREFIX = ""; 358 | }; 359 | name = Debug; 360 | }; 361 | B08BC08C25C5143D00C08C81 /* Release */ = { 362 | isa = XCBuildConfiguration; 363 | buildSettings = { 364 | CLANG_ENABLE_MODULES = YES; 365 | CODE_SIGN_STYLE = Automatic; 366 | COMBINE_HIDPI_IMAGES = YES; 367 | CURRENT_PROJECT_VERSION = 1; 368 | DEFINES_MODULE = YES; 369 | DEVELOPMENT_TEAM = 2ZDN69KUUV; 370 | DYLIB_COMPATIBILITY_VERSION = 1; 371 | DYLIB_CURRENT_VERSION = 1; 372 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 373 | INFOPLIST_FILE = AppKitIntegration/Info.plist; 374 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 375 | LD_RUNPATH_SEARCH_PATHS = ( 376 | "$(inherited)", 377 | "@executable_path/../Frameworks", 378 | "@loader_path/Frameworks", 379 | ); 380 | MACOSX_DEPLOYMENT_TARGET = 11.1; 381 | PRODUCT_BUNDLE_IDENTIFIER = com.highcaffeinecontent.AppKitIntegration; 382 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; 383 | SDKROOT = macosx; 384 | SKIP_INSTALL = YES; 385 | SWIFT_VERSION = 5.0; 386 | VERSIONING_SYSTEM = "apple-generic"; 387 | VERSION_INFO_PREFIX = ""; 388 | }; 389 | name = Release; 390 | }; 391 | B0A6BA9425C26B4B007F945E /* Debug */ = { 392 | isa = XCBuildConfiguration; 393 | buildSettings = { 394 | ALWAYS_SEARCH_USER_PATHS = NO; 395 | CLANG_ANALYZER_NONNULL = YES; 396 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 397 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 398 | CLANG_CXX_LIBRARY = "libc++"; 399 | CLANG_ENABLE_MODULES = YES; 400 | CLANG_ENABLE_OBJC_ARC = YES; 401 | CLANG_ENABLE_OBJC_WEAK = YES; 402 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 403 | CLANG_WARN_BOOL_CONVERSION = YES; 404 | CLANG_WARN_COMMA = YES; 405 | CLANG_WARN_CONSTANT_CONVERSION = YES; 406 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 407 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 408 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 409 | CLANG_WARN_EMPTY_BODY = YES; 410 | CLANG_WARN_ENUM_CONVERSION = YES; 411 | CLANG_WARN_INFINITE_RECURSION = YES; 412 | CLANG_WARN_INT_CONVERSION = YES; 413 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 414 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 415 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 416 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 417 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 418 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 419 | CLANG_WARN_STRICT_PROTOTYPES = YES; 420 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 421 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 422 | CLANG_WARN_UNREACHABLE_CODE = YES; 423 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 424 | COPY_PHASE_STRIP = NO; 425 | DEBUG_INFORMATION_FORMAT = dwarf; 426 | ENABLE_STRICT_OBJC_MSGSEND = YES; 427 | ENABLE_TESTABILITY = YES; 428 | GCC_C_LANGUAGE_STANDARD = gnu11; 429 | GCC_DYNAMIC_NO_PIC = NO; 430 | GCC_NO_COMMON_BLOCKS = YES; 431 | GCC_OPTIMIZATION_LEVEL = 0; 432 | GCC_PREPROCESSOR_DEFINITIONS = ( 433 | "DEBUG=1", 434 | "$(inherited)", 435 | ); 436 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 437 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 438 | GCC_WARN_UNDECLARED_SELECTOR = YES; 439 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 440 | GCC_WARN_UNUSED_FUNCTION = YES; 441 | GCC_WARN_UNUSED_VARIABLE = YES; 442 | IPHONEOS_DEPLOYMENT_TARGET = 14.4; 443 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 444 | MTL_FAST_MATH = YES; 445 | ONLY_ACTIVE_ARCH = YES; 446 | SDKROOT = iphoneos; 447 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 448 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 449 | }; 450 | name = Debug; 451 | }; 452 | B0A6BA9525C26B4B007F945E /* Release */ = { 453 | isa = XCBuildConfiguration; 454 | buildSettings = { 455 | ALWAYS_SEARCH_USER_PATHS = NO; 456 | CLANG_ANALYZER_NONNULL = YES; 457 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 458 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 459 | CLANG_CXX_LIBRARY = "libc++"; 460 | CLANG_ENABLE_MODULES = YES; 461 | CLANG_ENABLE_OBJC_ARC = YES; 462 | CLANG_ENABLE_OBJC_WEAK = YES; 463 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 464 | CLANG_WARN_BOOL_CONVERSION = YES; 465 | CLANG_WARN_COMMA = YES; 466 | CLANG_WARN_CONSTANT_CONVERSION = YES; 467 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 468 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 469 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 470 | CLANG_WARN_EMPTY_BODY = YES; 471 | CLANG_WARN_ENUM_CONVERSION = YES; 472 | CLANG_WARN_INFINITE_RECURSION = YES; 473 | CLANG_WARN_INT_CONVERSION = YES; 474 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 475 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 476 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 477 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 478 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 479 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 480 | CLANG_WARN_STRICT_PROTOTYPES = YES; 481 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 482 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 483 | CLANG_WARN_UNREACHABLE_CODE = YES; 484 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 485 | COPY_PHASE_STRIP = NO; 486 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 487 | ENABLE_NS_ASSERTIONS = NO; 488 | ENABLE_STRICT_OBJC_MSGSEND = YES; 489 | GCC_C_LANGUAGE_STANDARD = gnu11; 490 | GCC_NO_COMMON_BLOCKS = YES; 491 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 492 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 493 | GCC_WARN_UNDECLARED_SELECTOR = YES; 494 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 495 | GCC_WARN_UNUSED_FUNCTION = YES; 496 | GCC_WARN_UNUSED_VARIABLE = YES; 497 | IPHONEOS_DEPLOYMENT_TARGET = 14.4; 498 | MTL_ENABLE_DEBUG_INFO = NO; 499 | MTL_FAST_MATH = YES; 500 | SDKROOT = iphoneos; 501 | SWIFT_COMPILATION_MODE = wholemodule; 502 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 503 | VALIDATE_PRODUCT = YES; 504 | }; 505 | name = Release; 506 | }; 507 | B0A6BA9725C26B4B007F945E /* Debug */ = { 508 | isa = XCBuildConfiguration; 509 | buildSettings = { 510 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 511 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 512 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 513 | CODE_SIGN_ENTITLEMENTS = smalltext/smalltext.entitlements; 514 | CODE_SIGN_STYLE = Automatic; 515 | CURRENT_PROJECT_VERSION = 2; 516 | DEVELOPMENT_TEAM = 2ZDN69KUUV; 517 | INFOPLIST_FILE = smalltext/Info.plist; 518 | IPHONEOS_DEPLOYMENT_TARGET = 14.1; 519 | LD_RUNPATH_SEARCH_PATHS = ( 520 | "$(inherited)", 521 | "@executable_path/Frameworks", 522 | ); 523 | MARKETING_VERSION = 3.0; 524 | PRODUCT_BUNDLE_IDENTIFIER = com.highcaffeinecontent.smalltext; 525 | PRODUCT_NAME = "$(TARGET_NAME)"; 526 | SUPPORTS_MACCATALYST = YES; 527 | SWIFT_VERSION = 5.0; 528 | TARGETED_DEVICE_FAMILY = "1,2,6"; 529 | }; 530 | name = Debug; 531 | }; 532 | B0A6BA9825C26B4B007F945E /* Release */ = { 533 | isa = XCBuildConfiguration; 534 | buildSettings = { 535 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 536 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 537 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 538 | CODE_SIGN_ENTITLEMENTS = smalltext/smalltext.entitlements; 539 | CODE_SIGN_STYLE = Automatic; 540 | CURRENT_PROJECT_VERSION = 2; 541 | DEVELOPMENT_TEAM = 2ZDN69KUUV; 542 | INFOPLIST_FILE = smalltext/Info.plist; 543 | IPHONEOS_DEPLOYMENT_TARGET = 14.1; 544 | LD_RUNPATH_SEARCH_PATHS = ( 545 | "$(inherited)", 546 | "@executable_path/Frameworks", 547 | ); 548 | MARKETING_VERSION = 3.0; 549 | PRODUCT_BUNDLE_IDENTIFIER = com.highcaffeinecontent.smalltext; 550 | PRODUCT_NAME = "$(TARGET_NAME)"; 551 | SUPPORTS_MACCATALYST = YES; 552 | SWIFT_VERSION = 5.0; 553 | TARGETED_DEVICE_FAMILY = "1,2,6"; 554 | }; 555 | name = Release; 556 | }; 557 | /* End XCBuildConfiguration section */ 558 | 559 | /* Begin XCConfigurationList section */ 560 | B08BC08D25C5143D00C08C81 /* Build configuration list for PBXNativeTarget "AppKitIntegration" */ = { 561 | isa = XCConfigurationList; 562 | buildConfigurations = ( 563 | B08BC08B25C5143D00C08C81 /* Debug */, 564 | B08BC08C25C5143D00C08C81 /* Release */, 565 | ); 566 | defaultConfigurationIsVisible = 0; 567 | defaultConfigurationName = Release; 568 | }; 569 | B0A6BA7B25C26B49007F945E /* Build configuration list for PBXProject "smalltext" */ = { 570 | isa = XCConfigurationList; 571 | buildConfigurations = ( 572 | B0A6BA9425C26B4B007F945E /* Debug */, 573 | B0A6BA9525C26B4B007F945E /* Release */, 574 | ); 575 | defaultConfigurationIsVisible = 0; 576 | defaultConfigurationName = Release; 577 | }; 578 | B0A6BA9625C26B4B007F945E /* Build configuration list for PBXNativeTarget "smalltext" */ = { 579 | isa = XCConfigurationList; 580 | buildConfigurations = ( 581 | B0A6BA9725C26B4B007F945E /* Debug */, 582 | B0A6BA9825C26B4B007F945E /* Release */, 583 | ); 584 | defaultConfigurationIsVisible = 0; 585 | defaultConfigurationName = Release; 586 | }; 587 | /* End XCConfigurationList section */ 588 | }; 589 | rootObject = B0A6BA7825C26B49007F945E /* Project object */; 590 | } 591 | -------------------------------------------------------------------------------- /smalltext.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /smalltext/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /smalltext/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "scale" : "2x", 6 | "size" : "20x20" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "scale" : "3x", 11 | "size" : "20x20" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "scale" : "2x", 16 | "size" : "29x29" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "scale" : "3x", 21 | "size" : "29x29" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "scale" : "2x", 26 | "size" : "40x40" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "scale" : "3x", 31 | "size" : "40x40" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "scale" : "2x", 36 | "size" : "60x60" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "scale" : "3x", 41 | "size" : "60x60" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "scale" : "1x", 46 | "size" : "20x20" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "scale" : "2x", 51 | "size" : "20x20" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "scale" : "1x", 56 | "size" : "29x29" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "scale" : "2x", 61 | "size" : "29x29" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "scale" : "1x", 66 | "size" : "40x40" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "scale" : "2x", 71 | "size" : "40x40" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "scale" : "1x", 76 | "size" : "76x76" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "scale" : "2x", 81 | "size" : "76x76" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "scale" : "2x", 86 | "size" : "83.5x83.5" 87 | }, 88 | { 89 | "filename" : "SmallText-BigSur-1.png", 90 | "idiom" : "ios-marketing", 91 | "scale" : "1x", 92 | "size" : "1024x1024" 93 | }, 94 | { 95 | "idiom" : "mac", 96 | "scale" : "1x", 97 | "size" : "16x16" 98 | }, 99 | { 100 | "idiom" : "mac", 101 | "scale" : "2x", 102 | "size" : "16x16" 103 | }, 104 | { 105 | "idiom" : "mac", 106 | "scale" : "1x", 107 | "size" : "32x32" 108 | }, 109 | { 110 | "idiom" : "mac", 111 | "scale" : "2x", 112 | "size" : "32x32" 113 | }, 114 | { 115 | "idiom" : "mac", 116 | "scale" : "1x", 117 | "size" : "128x128" 118 | }, 119 | { 120 | "idiom" : "mac", 121 | "scale" : "2x", 122 | "size" : "128x128" 123 | }, 124 | { 125 | "idiom" : "mac", 126 | "scale" : "1x", 127 | "size" : "256x256" 128 | }, 129 | { 130 | "idiom" : "mac", 131 | "scale" : "2x", 132 | "size" : "256x256" 133 | }, 134 | { 135 | "filename" : "SmallText-BigSur@0.5x.png", 136 | "idiom" : "mac", 137 | "scale" : "1x", 138 | "size" : "512x512" 139 | }, 140 | { 141 | "filename" : "SmallText-BigSur.png", 142 | "idiom" : "mac", 143 | "scale" : "2x", 144 | "size" : "512x512" 145 | } 146 | ], 147 | "info" : { 148 | "author" : "xcode", 149 | "version" : 1 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /smalltext/Assets.xcassets/AppIcon.appiconset/SmallText-BigSur-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/steventroughtonsmith/smalltext/f81b78c37c95ec77f36a34f5accb7fae99e2a7ca/smalltext/Assets.xcassets/AppIcon.appiconset/SmallText-BigSur-1.png -------------------------------------------------------------------------------- /smalltext/Assets.xcassets/AppIcon.appiconset/SmallText-BigSur.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/steventroughtonsmith/smalltext/f81b78c37c95ec77f36a34f5accb7fae99e2a7ca/smalltext/Assets.xcassets/AppIcon.appiconset/SmallText-BigSur.png -------------------------------------------------------------------------------- /smalltext/Assets.xcassets/AppIcon.appiconset/SmallText-BigSur@0.5x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/steventroughtonsmith/smalltext/f81b78c37c95ec77f36a34f5accb7fae99e2a7ca/smalltext/Assets.xcassets/AppIcon.appiconset/SmallText-BigSur@0.5x.png -------------------------------------------------------------------------------- /smalltext/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /smalltext/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /smalltext/Controllers/STXAppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // smalltext 4 | // 5 | // Created by Steven Troughton-Smith on 28/01/2021. 6 | // 7 | 8 | import UIKit 9 | 10 | extension NSObject { 11 | @objc public func _marzipan_setupWindow(_ sender:Any) { 12 | 13 | } 14 | 15 | @objc public func hideWindowForSceneIdentifier(_ sceneIdentifier:String) { 16 | 17 | } 18 | 19 | @objc public func showWindowForSceneIdentifier(_ sceneIdentifier:String) { 20 | 21 | } 22 | } 23 | 24 | @main 25 | class STXAppDelegate: UIResponder, UIApplicationDelegate { 26 | 27 | var window: UIWindow? 28 | 29 | #if targetEnvironment(macCatalyst) 30 | 31 | static var appKitController:NSObject? 32 | 33 | class func loadAppKitIntegrationFramework() { 34 | 35 | if let frameworksPath = Bundle.main.privateFrameworksPath { 36 | let bundlePath = "\(frameworksPath)/AppKitIntegration.framework" 37 | do { 38 | try Bundle(path: bundlePath)?.loadAndReturnError() 39 | 40 | let bundle = Bundle(path: bundlePath)! 41 | NSLog("[APPKIT BUNDLE] Loaded Successfully") 42 | 43 | if let appKitControllerClass = bundle.classNamed("AppKitIntegration.AppKitController") as? NSObject.Type { 44 | appKitController = appKitControllerClass.init() 45 | 46 | if let appKitController = appKitController { 47 | NotificationCenter.default.addObserver(appKitController, selector: #selector(_marzipan_setupWindow(_:)), name: NSNotification.Name("UISBHSDidCreateWindowForSceneNotification"), object: nil) 48 | } 49 | } 50 | } 51 | catch { 52 | NSLog("[APPKIT BUNDLE] Error loading: \(error)") 53 | } 54 | } 55 | } 56 | #endif 57 | 58 | 59 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 60 | // Override point for customization after application launch. 61 | 62 | #if targetEnvironment(macCatalyst) 63 | STXAppDelegate.loadAppKitIntegrationFramework() 64 | #endif 65 | 66 | return true 67 | } 68 | 69 | func applicationWillResignActive(_ application: UIApplication) { 70 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 71 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 72 | } 73 | 74 | func applicationDidEnterBackground(_ application: UIApplication) { 75 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 76 | } 77 | 78 | func applicationWillEnterForeground(_ application: UIApplication) { 79 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 80 | } 81 | 82 | func applicationDidBecomeActive(_ application: UIApplication) { 83 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 84 | } 85 | 86 | func application(_ app: UIApplication, open inputURL: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool { 87 | // Ensure the URL is a file URL 88 | guard inputURL.isFileURL else { return false } 89 | 90 | // Reveal / import the document at the URL 91 | guard let documentBrowserViewController = window?.rootViewController as? STXDocumentBrowserViewController else { return false } 92 | 93 | documentBrowserViewController.revealDocument(at: inputURL, importIfNeeded: true) { (revealedDocumentURL, error) in 94 | if let error = error { 95 | // Handle the error appropriately 96 | print("Failed to reveal the document at URL \(inputURL) with error: '\(error)'") 97 | return 98 | } 99 | 100 | // Present the Document View Controller for the revealed URL 101 | documentBrowserViewController.presentDocument(at: revealedDocumentURL!) 102 | } 103 | 104 | return true 105 | } 106 | 107 | } 108 | 109 | -------------------------------------------------------------------------------- /smalltext/Controllers/STXDocumentBrowserViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DocumentBrowserViewController.swift 3 | // smalltext 4 | // 5 | // Created by Steven Troughton-Smith on 28/01/2021. 6 | // 7 | 8 | import UIKit 9 | import SwiftUI 10 | 11 | class STXDocumentBrowserViewController: UIDocumentBrowserViewController, UIDocumentBrowserViewControllerDelegate { 12 | 13 | override func viewDidLoad() { 14 | super.viewDidLoad() 15 | 16 | delegate = self 17 | 18 | allowsDocumentCreation = true 19 | allowsPickingMultipleItems = false 20 | 21 | // Specify the allowed content types of your application via the Info.plist. 22 | 23 | // Do any additional setup after loading the view. 24 | } 25 | 26 | 27 | // MARK: UIDocumentBrowserViewControllerDelegate 28 | 29 | func documentBrowser(_ controller: UIDocumentBrowserViewController, didRequestDocumentCreationWithHandler importHandler: @escaping (URL?, UIDocumentBrowserViewController.ImportMode) -> Void) { 30 | let newDocumentURL: URL? = nil 31 | 32 | // Set the URL for the new document here. Optionally, you can present a template chooser before calling the importHandler. 33 | // Make sure the importHandler is always called, even if the user cancels the creation request. 34 | if newDocumentURL != nil { 35 | importHandler(newDocumentURL, .move) 36 | } else { 37 | importHandler(nil, .none) 38 | } 39 | } 40 | 41 | func documentBrowser(_ controller: UIDocumentBrowserViewController, didPickDocumentsAt documentURLs: [URL]) { 42 | guard let sourceURL = documentURLs.first else { return } 43 | 44 | // Present the Document View Controller for the first document that was picked. 45 | // If you support picking multiple items, make sure you handle them all. 46 | presentDocument(at: sourceURL) 47 | } 48 | 49 | func documentBrowser(_ controller: UIDocumentBrowserViewController, didImportDocumentAt sourceURL: URL, toDestinationURL destinationURL: URL) { 50 | // Present the Document View Controller for the new newly created document 51 | presentDocument(at: destinationURL) 52 | } 53 | 54 | func documentBrowser(_ controller: UIDocumentBrowserViewController, failedToImportDocumentAt documentURL: URL, error: Error?) { 55 | // Make sure to handle the failed import appropriately, e.g., by presenting an error message to the user. 56 | } 57 | 58 | // MARK: Document Presentation 59 | 60 | func presentDocument(at documentURL: URL) { 61 | let document = STXDocument(fileURL: documentURL) 62 | 63 | // Access the document 64 | document.open(completionHandler: { success in 65 | if success { 66 | 67 | let documentViewController = STXDocumentViewController() 68 | documentViewController.document = document 69 | 70 | #if targetEnvironment(macCatalyst) 71 | self.view.window?.windowScene?.titlebar?.representedURL = document.fileURL 72 | #endif 73 | self.view.window?.windowScene?.title = document.fileURL.lastPathComponent 74 | 75 | let animated = (UIDevice.current.userInterfaceIdiom == .mac) ? false : true 76 | 77 | documentViewController.modalPresentationStyle = .overFullScreen 78 | 79 | self.present(documentViewController, animated: animated, completion: nil) 80 | } else { 81 | 82 | } 83 | }) 84 | } 85 | 86 | func closeDocument(_ document: STXDocument) { 87 | dismiss(animated: true) { 88 | document.close(completionHandler: nil) 89 | } 90 | } 91 | } 92 | 93 | -------------------------------------------------------------------------------- /smalltext/Controllers/STXWindowScene.swift: -------------------------------------------------------------------------------- 1 | // 2 | // WindowScene.swift 3 | // issues 4 | // 5 | // Created by Steven Troughton-Smith on 20/09/2020. 6 | // 7 | 8 | import UIKit 9 | 10 | class STXWindowScene : NSObject, UISceneDelegate, UIWindowSceneDelegate { 11 | var window: UIWindow? 12 | 13 | func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { 14 | window = UIWindow(windowScene: scene as! UIWindowScene) 15 | 16 | NSLog("id = \(session.persistentIdentifier)") 17 | 18 | if let window = window { 19 | let documentBrowserViewController = STXDocumentBrowserViewController() 20 | window.rootViewController = documentBrowserViewController 21 | window.makeKeyAndVisible() 22 | 23 | #if targetEnvironment(macCatalyst) 24 | window.windowScene?.sizeRestrictions?.minimumSize = CGSize(width: UIFloat(320), height: UIFloat(320)) 25 | #endif 26 | } 27 | } 28 | 29 | func scene(_ scene: UIScene, openURLContexts URLContexts: Set) { 30 | 31 | guard let inputURL = URLContexts.first?.url else { return } 32 | guard inputURL.isFileURL else { return } 33 | 34 | // Reveal / import the document at the URL 35 | guard let documentBrowserViewController = window?.rootViewController as? STXDocumentBrowserViewController else { return } 36 | 37 | documentBrowserViewController.revealDocument(at: inputURL, importIfNeeded: true) { (revealedDocumentURL, error) in 38 | if let error = error { 39 | // Handle the error appropriately 40 | print("Failed to reveal the document at URL \(inputURL) with error: '\(error)'") 41 | return 42 | } 43 | 44 | // Present the Document View Controller for the revealed URL 45 | documentBrowserViewController.presentDocument(at: revealedDocumentURL!) 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /smalltext/Document Editor/STXDocument.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Document.swift 3 | // smalltext 4 | // 5 | // Created by Steven Troughton-Smith on 28/01/2021. 6 | // 7 | 8 | import UIKit 9 | 10 | class STXDocument: UIDocument { 11 | 12 | var body = "" 13 | 14 | override func contents(forType typeName: String) throws -> Any { 15 | return Data() 16 | } 17 | 18 | override func load(fromContents contents: Any, ofType typeName: String?) throws { 19 | if let data = contents as? Data { 20 | body = String(data: data, encoding: .utf8) ?? "" 21 | } else if let wrapper = contents as? FileWrapper { 22 | body = String(data: wrapper.regularFileContents!, encoding: .utf8) ?? "" 23 | } 24 | } 25 | 26 | func text() -> String { 27 | return body 28 | } 29 | } 30 | 31 | -------------------------------------------------------------------------------- /smalltext/Document Editor/STXDocumentViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // STXDocumentViewController.swift 3 | // smalltext 4 | // 5 | // Created by Steven Troughton-Smith on 28/01/2021. 6 | // 7 | 8 | import UIKit 9 | 10 | class STXDocumentViewController: UIViewController, UIColorPickerViewControllerDelegate, UIFontPickerViewControllerDelegate { 11 | 12 | var colorPickerViewController = UIColorPickerViewController() 13 | 14 | let textView = UITextView() 15 | 16 | let toolbarView = STXVisualEffectView(blurStyle: .systemChromeMaterial) 17 | 18 | let textSwatch = STXColorButton() 19 | let backgroundSwatch = STXColorButton() 20 | let fontButton = STXFontButton() 21 | 22 | enum STXColorPickerMemory { 23 | case text 24 | case background 25 | } 26 | 27 | var currentColorPicker = STXColorPickerMemory.text 28 | 29 | var font = UIFont.systemFont(ofSize: UIFloat(16)) { 30 | didSet { 31 | textView.font = font 32 | fontButton.documentFont = font 33 | } 34 | } 35 | 36 | public var document:STXDocument? { 37 | didSet { 38 | textView.text = document!.text() 39 | } 40 | } 41 | 42 | override func viewDidLoad() { 43 | super.viewDidLoad() 44 | 45 | view.backgroundColor = .systemBackground 46 | 47 | textView.frame = view.bounds 48 | textView.alwaysBounceVertical = true 49 | textView.insetsLayoutMarginsFromSafeArea = true 50 | textView.automaticallyAdjustsScrollIndicatorInsets = false 51 | 52 | view.addSubview(textView) 53 | 54 | let hairlineView = STXHairlineDividerView() 55 | hairlineView.autoresizingMask = [.flexibleWidth, .flexibleHeight] 56 | hairlineView.borderMask = .bottom 57 | 58 | toolbarView.contentView.addSubview(hairlineView) 59 | 60 | toolbarView.contentView.addSubview(textSwatch) 61 | toolbarView.contentView.addSubview(backgroundSwatch) 62 | toolbarView.contentView.addSubview(fontButton) 63 | 64 | textSwatch.glyph.image = UIImage(systemName: "textformat") 65 | backgroundSwatch.glyph.image = UIImage(systemName: "doc.text.fill") 66 | fontButton.label.text = "SF Display" 67 | 68 | backgroundSwatch.color = .white 69 | 70 | font = UIFont(name: "Monaco", size: UIFloat(16)) ?? UIFont.systemFont(ofSize: UIFloat(16)) 71 | 72 | textSwatch.addTarget(self, action: #selector(pickTextColor(_:)), for: .touchUpInside) 73 | backgroundSwatch.addTarget(self, action: #selector(pickBackgroundColor(_:)), for: .touchUpInside) 74 | 75 | fontButton.addTarget(self, action: #selector(pickFont(_:)), for: .touchUpInside) 76 | 77 | view.addSubview(toolbarView) 78 | } 79 | 80 | // MARK: - 81 | 82 | override func viewDidLayoutSubviews() { 83 | 84 | let swatchWidth = UIFloat(60) 85 | let swatchHeight = UIFloat(28) 86 | let padding = UIFloat(8) 87 | let topBarHeight = swatchHeight + padding * 2 88 | 89 | let safeRect = view.bounds.inset(by: view.safeAreaInsets) 90 | let divisor = safeRect.divided(atDistance: topBarHeight, from: .minYEdge) 91 | 92 | 93 | let combinedSafeInset = UIEdgeInsets(top: view.safeAreaInsets.top + topBarHeight, left: view.safeAreaInsets.left, bottom: view.safeAreaInsets.bottom, right: view.safeAreaInsets.right) 94 | 95 | textView.contentInset = view.safeAreaInsets 96 | textView.scrollIndicatorInsets = combinedSafeInset 97 | textView.frame = view.bounds 98 | 99 | var topBarRect = divisor.slice 100 | 101 | topBarRect.origin.y = 0 102 | topBarRect.size.height += view.safeAreaInsets.top 103 | 104 | toolbarView.frame = topBarRect 105 | 106 | textSwatch.frame = CGRect(x: padding, y: view.safeAreaInsets.top + padding, width: swatchWidth, height: swatchHeight) 107 | backgroundSwatch.frame = CGRect(x: topBarRect.maxX-padding-swatchWidth, y: view.safeAreaInsets.top + padding, width: swatchWidth, height: swatchHeight) 108 | 109 | fontButton.frame = CGRect(x: textSwatch.frame.maxX + padding, y: view.safeAreaInsets.top + padding, width: backgroundSwatch.frame.minX - padding - (textSwatch.frame.maxX + padding), height: swatchHeight) 110 | } 111 | 112 | // MARK: - Actions 113 | 114 | @objc func pickFont(_ sender:Any) { 115 | 116 | let config = UIFontPickerViewController.Configuration() 117 | config.includeFaces = true 118 | 119 | let vc = UIFontPickerViewController(configuration: config) 120 | vc.delegate = self 121 | vc.modalPresentationStyle = .popover 122 | vc.popoverPresentationController?.sourceView = fontButton 123 | 124 | present(vc, animated: true, completion: nil) 125 | } 126 | 127 | @objc func pickTextColor(_ sender:Any) { 128 | colorPickerViewController = UIColorPickerViewController() 129 | 130 | colorPickerViewController.delegate = self 131 | colorPickerViewController.modalPresentationStyle = .popover 132 | colorPickerViewController.popoverPresentationController?.sourceView = textSwatch 133 | 134 | colorPickerViewController.selectedColor = textSwatch.color 135 | 136 | currentColorPicker = .text 137 | 138 | present(colorPickerViewController, animated: true, completion: nil) 139 | } 140 | 141 | @objc func pickBackgroundColor(_ sender:Any) { 142 | colorPickerViewController = UIColorPickerViewController() 143 | 144 | colorPickerViewController.delegate = self 145 | colorPickerViewController.modalPresentationStyle = .popover 146 | colorPickerViewController.popoverPresentationController?.sourceView = backgroundSwatch 147 | 148 | colorPickerViewController.selectedColor = backgroundSwatch.color 149 | 150 | currentColorPicker = .background 151 | 152 | present(colorPickerViewController, animated: true, completion: nil) 153 | } 154 | 155 | // MARK: - UIColorPickerViewControllerDelegate 156 | 157 | func colorPickerViewControllerDidSelectColor(_ viewController: UIColorPickerViewController) { 158 | if currentColorPicker == .text { 159 | textView.textColor = colorPickerViewController.selectedColor 160 | textSwatch.color = colorPickerViewController.selectedColor 161 | } 162 | else { 163 | textView.backgroundColor = colorPickerViewController.selectedColor 164 | backgroundSwatch.color = colorPickerViewController.selectedColor 165 | } 166 | } 167 | 168 | func colorPickerViewControllerDidFinish(_ viewController: UIColorPickerViewController) { 169 | if currentColorPicker == .text { 170 | textView.textColor = colorPickerViewController.selectedColor 171 | textSwatch.color = colorPickerViewController.selectedColor 172 | } 173 | else { 174 | textView.backgroundColor = colorPickerViewController.selectedColor 175 | backgroundSwatch.color = colorPickerViewController.selectedColor 176 | } 177 | } 178 | 179 | // MARK: - UIFontPickerViewControllerDelegate 180 | 181 | func fontPickerViewControllerDidPickFont(_ viewController: UIFontPickerViewController) { 182 | 183 | if let descriptor = viewController.selectedFontDescriptor { 184 | let font = UIFont(descriptor: descriptor, size: descriptor.pointSize) 185 | fontButton.documentFont = font 186 | textView.font = font 187 | } 188 | } 189 | 190 | } 191 | -------------------------------------------------------------------------------- /smalltext/Document Editor/Toolbar Views/STXColorButton.swift: -------------------------------------------------------------------------------- 1 | // 2 | // STXColorButton.swift 3 | // smalltext 4 | // 5 | // Created by Steven Troughton-Smith on 29/01/2021. 6 | // 7 | 8 | import UIKit 9 | 10 | class STXColorButton: UIButton { 11 | 12 | var color = UIColor.black { 13 | didSet { 14 | colorSwatch.backgroundColor = color 15 | } 16 | } 17 | 18 | override var isHighlighted: Bool { 19 | didSet { 20 | visualEffectView.contentView.backgroundColor = isHighlighted ? .separator : .clear 21 | } 22 | } 23 | 24 | let visualEffectView = STXVisualEffectView(blurStyle: .systemThickMaterial) 25 | let colorSwatch = UIView() 26 | let label = UILabel() 27 | let glyph = UIImageView() 28 | 29 | override init(frame: CGRect) { 30 | super.init(frame: frame) 31 | 32 | layer.masksToBounds = true 33 | layer.cornerCurve = .continuous 34 | 35 | glyph.contentMode = .scaleAspectFit 36 | glyph.tintColor = UIColor.label 37 | 38 | colorSwatch.backgroundColor = color 39 | 40 | layer.borderWidth = 1.0 / UIScreen.main.scale 41 | layer.borderColor = UIColor.separator.cgColor 42 | 43 | colorSwatch.layer.borderWidth = 1.0 / UIScreen.main.scale 44 | colorSwatch.layer.borderColor = UIColor.separator.cgColor 45 | colorSwatch.isUserInteractionEnabled = false 46 | 47 | addSubview(visualEffectView) 48 | addSubview(colorSwatch) 49 | 50 | label.font = UIFont.systemFont(ofSize: UIFloat(13)) 51 | label.textAlignment = .center 52 | 53 | visualEffectView.addContentView(glyph) 54 | visualEffectView.isUserInteractionEnabled = false 55 | } 56 | 57 | convenience init() { 58 | self.init(frame:.zero) 59 | } 60 | 61 | required init?(coder: NSCoder) { 62 | fatalError("init(coder:) has not been implemented") 63 | } 64 | 65 | // MARK: - 66 | 67 | override func tintColorDidChange() { 68 | colorSwatch.layer.borderColor = UIColor.separator.cgColor 69 | layer.borderColor = UIColor.separator.cgColor 70 | } 71 | 72 | override func layoutSubviews() { 73 | super.layoutSubviews() 74 | visualEffectView.frame = bounds 75 | 76 | let swatchSize = bounds.height 77 | let inset = UIFloat(4) 78 | let cornerRadius = UIFloat(8) 79 | 80 | colorSwatch.frame = CGRect(x: bounds.maxX-swatchSize, y: 0, width: swatchSize, height: swatchSize).insetBy(dx: inset, dy: inset) 81 | glyph.frame = CGRect(x: inset, y: 0, width: bounds.maxX-swatchSize, height: bounds.height).insetBy(dx: inset, dy: inset) 82 | 83 | layer.cornerRadius = cornerRadius 84 | colorSwatch.layer.cornerRadius = colorSwatch.bounds.midY 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /smalltext/Document Editor/Toolbar Views/STXFontButton.swift: -------------------------------------------------------------------------------- 1 | // 2 | // STXFontButton.swift 3 | // smalltext 4 | // 5 | // Created by Steven Troughton-Smith on 29/01/2021. 6 | // 7 | 8 | import UIKit 9 | 10 | class STXFontButton: UIButton { 11 | 12 | let visualEffectView = STXVisualEffectView(blurStyle: .systemThickMaterial) 13 | 14 | let label = UILabel() 15 | 16 | var documentFont = UIFont.systemFont(ofSize: UIFloat(13)) { 17 | didSet { 18 | label.text = "\(documentFont.fontName) \(documentFont.pointSize)" 19 | } 20 | } 21 | 22 | override var isHighlighted: Bool { 23 | didSet { 24 | visualEffectView.backgroundColor = isHighlighted ? .systemFill : .clear 25 | } 26 | } 27 | 28 | override init(frame: CGRect) { 29 | super.init(frame: frame) 30 | 31 | layer.masksToBounds = true 32 | layer.cornerCurve = .continuous 33 | 34 | layer.borderWidth = 1.0 / UIScreen.main.scale 35 | layer.borderColor = UIColor.separator.cgColor 36 | 37 | addSubview(visualEffectView) 38 | 39 | label.font = UIFont.systemFont(ofSize: UIFloat(13)) 40 | label.textAlignment = .center 41 | label.textColor = UIColor.label 42 | 43 | visualEffectView.contentView.addSubview(label) 44 | 45 | visualEffectView.isUserInteractionEnabled = false 46 | } 47 | 48 | convenience init() { 49 | self.init(frame:.zero) 50 | } 51 | 52 | required init?(coder: NSCoder) { 53 | fatalError("init(coder:) has not been implemented") 54 | } 55 | 56 | // MARK: - 57 | 58 | override func tintColorDidChange() { 59 | layer.borderColor = UIColor.separator.cgColor 60 | } 61 | 62 | override func layoutSubviews() { 63 | super.layoutSubviews() 64 | visualEffectView.frame = bounds 65 | 66 | let inset = UIFloat(4) 67 | let cornerRadius = UIFloat(8) 68 | 69 | label.frame = bounds.insetBy(dx: inset, dy: inset) 70 | 71 | layer.cornerRadius = cornerRadius 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /smalltext/Document Editor/Toolbar Views/STXHairlineDividerView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PSTLHairlineDividerView.swift 3 | // Pastel 4 | // 5 | // Created by Steven Troughton-Smith on 31/08/2021. 6 | // Copyright © 2021 Steven Troughton-Smith. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | extension UIRectEdge { 12 | static let centeredVertically = UIRectEdge.init(rawValue:1<<7) 13 | static let centeredHorizontally = UIRectEdge.init(rawValue:1<<8) 14 | } 15 | 16 | class STXHairlineDividerView: UIView { 17 | 18 | @objc var dividerColor = UIColor.clear { 19 | didSet { 20 | setNeedsDisplay() 21 | } 22 | } 23 | 24 | var borderMask:UIRectEdge = [] 25 | 26 | init() { 27 | super.init(frame: .zero) 28 | 29 | backgroundColor = .clear 30 | dividerColor = .separator 31 | } 32 | 33 | required init?(coder: NSCoder) { 34 | fatalError("init(coder:) has not been implemented") 35 | } 36 | 37 | override var frame: CGRect { 38 | didSet { 39 | setNeedsDisplay() 40 | } 41 | } 42 | 43 | // MARK: - 44 | 45 | override func draw(_ rect: CGRect) { 46 | 47 | var scale = 1.0 48 | 49 | if let screen = window?.screen { 50 | scale = screen.scale 51 | } 52 | 53 | let dividerWidth = 1.0/scale 54 | 55 | if backgroundColor != nil && backgroundColor != .clear { 56 | backgroundColor?.set() 57 | UIRectFill(bounds) 58 | } 59 | 60 | if dividerColor != .clear { 61 | dividerColor.set() 62 | 63 | if borderMask.contains(.top) == true { 64 | UIRectFill(CGRect(x: 0, y: 0, width: bounds.width, height: dividerWidth)) 65 | } 66 | 67 | if borderMask.contains(.left) == true { 68 | UIRectFill(CGRect(x: 0, y: 0, width: dividerWidth, height: bounds.height)) 69 | } 70 | 71 | if borderMask.contains(.bottom) == true { 72 | UIRectFill(CGRect(x: 0, y: bounds.height-dividerWidth, width: bounds.width, height: dividerWidth)) 73 | } 74 | 75 | if borderMask.contains(.right) == true { 76 | UIRectFill(CGRect(x: bounds.width-dividerWidth, y: 0, width: dividerWidth, height: bounds.height)) 77 | } 78 | 79 | if borderMask.contains(.centeredVertically) == true { 80 | UIRectFill(CGRect(x: bounds.midX-dividerWidth, y: 0, width: dividerWidth, height: bounds.height)) 81 | } 82 | 83 | if borderMask.contains(.centeredHorizontally) == true { 84 | UIRectFill(CGRect(x: 0, y: bounds.midY-dividerWidth, width: bounds.width, height: dividerWidth)) 85 | } 86 | } 87 | 88 | } 89 | 90 | } 91 | -------------------------------------------------------------------------------- /smalltext/Document Editor/Toolbar Views/STXVisualEffectView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MRDVisualEffectView.swift 3 | // MobileRadio 4 | // 5 | // Created by Steven Troughton-Smith on 13/09/2020. 6 | // Copyright © 2020 High Caffeine Content. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class STXVisualEffectView: UIVisualEffectView { 12 | 13 | let contentEffectView:UIVisualEffectView 14 | 15 | init(blurStyle: UIBlurEffect.Style) { 16 | let blurEffect = UIBlurEffect(style: blurStyle) 17 | let vibrancyEffect = UIVibrancyEffect(blurEffect: blurEffect) 18 | 19 | contentEffectView = UIVisualEffectView(effect: vibrancyEffect) 20 | super.init(effect: blurEffect) 21 | 22 | contentView.addSubview(contentEffectView) 23 | } 24 | 25 | init(blurStyle: UIBlurEffect.Style, blur2Style: UIBlurEffect.Style) { 26 | let blurEffect = UIBlurEffect(style: blurStyle) 27 | let blur2Effect = UIBlurEffect(style: blur2Style) 28 | let vibrancyEffect = UIVibrancyEffect(blurEffect: blur2Effect) 29 | 30 | contentEffectView = UIVisualEffectView(effect: vibrancyEffect) 31 | super.init(effect: blurEffect) 32 | 33 | contentView.addSubview(contentEffectView) 34 | } 35 | 36 | init() 37 | { 38 | contentEffectView = UIVisualEffectView(effect: nil) 39 | super.init(effect: nil) 40 | contentView.addSubview(contentEffectView) 41 | } 42 | 43 | required init?(coder: NSCoder) { 44 | fatalError("init(coder:) has not been implemented") 45 | } 46 | 47 | @objc func addContentView(_ view: UIView) { 48 | contentEffectView.contentView.addSubview(view) 49 | } 50 | 51 | override func layoutSubviews() { 52 | contentEffectView.frame = bounds 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /smalltext/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleDisplayName 8 | SmallText 9 | CFBundleDocumentTypes 10 | 11 | 12 | CFBundleTypeName 13 | Text File 14 | CFBundleTypeRole 15 | Editor 16 | LSHandlerRank 17 | Default 18 | LSItemContentTypes 19 | 20 | public.plain-text 21 | 22 | 23 | 24 | CFBundleExecutable 25 | $(EXECUTABLE_NAME) 26 | CFBundleIdentifier 27 | $(PRODUCT_BUNDLE_IDENTIFIER) 28 | CFBundleInfoDictionaryVersion 29 | 6.0 30 | CFBundleName 31 | $(PRODUCT_NAME) 32 | CFBundlePackageType 33 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 34 | CFBundleShortVersionString 35 | $(MARKETING_VERSION) 36 | CFBundleVersion 37 | $(CURRENT_PROJECT_VERSION) 38 | LSApplicationCategoryType 39 | public.app-category.utilities 40 | LSRequiresIPhoneOS 41 | 42 | LSSupportsOpeningDocumentsInPlace 43 | 44 | NSHumanReadableCopyright 45 | © 2021 Steven Troughton-Smith 46 | UIApplicationSceneManifest 47 | 48 | UIApplicationSupportsMultipleScenes 49 | 50 | UISceneConfigurations 51 | 52 | UIWindowSceneSessionRoleApplication 53 | 54 | 55 | UISceneConfigurationName 56 | Editor 57 | UISceneDelegateClassName 58 | $(PRODUCT_MODULE_NAME).STXWindowScene 59 | 60 | 61 | 62 | 63 | UIApplicationSupportsIndirectInputEvents 64 | 65 | UILaunchStoryboardName 66 | LaunchScreen 67 | UIRequiredDeviceCapabilities 68 | 69 | armv7 70 | 71 | UISupportedInterfaceOrientations 72 | 73 | UIInterfaceOrientationPortrait 74 | UIInterfaceOrientationLandscapeLeft 75 | UIInterfaceOrientationLandscapeRight 76 | 77 | UISupportedInterfaceOrientations~ipad 78 | 79 | UIInterfaceOrientationPortrait 80 | UIInterfaceOrientationPortraitUpsideDown 81 | UIInterfaceOrientationLandscapeLeft 82 | UIInterfaceOrientationLandscapeRight 83 | 84 | UISupportsDocumentBrowser 85 | 86 | UTImportedTypeDeclarations 87 | 88 | 89 | UTTypeConformsTo 90 | 91 | public.plain-text 92 | 93 | UTTypeDescription 94 | Example Text 95 | UTTypeIconFiles 96 | 97 | UTTypeIdentifier 98 | com.highcaffeinecontent.text 99 | UTTypeTagSpecification 100 | 101 | public.filename-extension 102 | 103 | txt 104 | 105 | 106 | 107 | 108 | 109 | 110 | -------------------------------------------------------------------------------- /smalltext/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* 2 | InfoPlist.strings 3 | smalltext 4 | 5 | Created by Steven Troughton-Smith on 29/01/2021. 6 | 7 | */ 8 | 9 | CFBundleName = "SmallText"; 10 | -------------------------------------------------------------------------------- /smalltext/Number+Scaling.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CGFloat+Scaling.swift 3 | // Voxcaster 4 | // 5 | // Created by Steven Troughton-Smith on 29/07/2020. 6 | // 7 | 8 | import UIKit 9 | 10 | public let supportsMacIdiom = !(UIDevice.current.userInterfaceIdiom == .pad) 11 | 12 | @inlinable func UIFloat(_ value: CGFloat) -> CGFloat 13 | { 14 | #if targetEnvironment(macCatalyst) 15 | return (value == 0.5) ? 0.5 : round(value * (supportsMacIdiom ? 0.77 : 1.0)) 16 | #else 17 | return value 18 | #endif 19 | } 20 | -------------------------------------------------------------------------------- /smalltext/WindowScene.swift: -------------------------------------------------------------------------------- 1 | // 2 | // WindowScene.swift 3 | // issues 4 | // 5 | // Created by Steven Troughton-Smith on 20/09/2020. 6 | // 7 | 8 | import UIKit 9 | 10 | class STXWindowScene : NSObject, UISceneDelegate, UIWindowSceneDelegate { 11 | var window: UIWindow? 12 | 13 | func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { 14 | window = UIWindow(windowScene: scene as! UIWindowScene) 15 | 16 | let documentBrowserViewController = DocumentBrowserViewController() 17 | window?.rootViewController = documentBrowserViewController 18 | window?.makeKeyAndVisible() 19 | 20 | window?.backgroundColor = .white 21 | 22 | #if targetEnvironment(macCatalyst) 23 | window?.windowScene?.titlebar?.toolbar = NSToolbar() 24 | window?.windowScene?.titlebar?.toolbarStyle = .automatic 25 | window?.windowScene?.titlebar?.separatorStyle = .none 26 | #endif 27 | } 28 | 29 | func scene(_ scene: UIScene, openURLContexts URLContexts: Set) { 30 | 31 | guard let inputURL = URLContexts.first?.url else { return } 32 | guard inputURL.isFileURL else { return } 33 | 34 | // Reveal / import the document at the URL 35 | guard let documentBrowserViewController = window?.rootViewController as? DocumentBrowserViewController else { return } 36 | 37 | documentBrowserViewController.revealDocument(at: inputURL, importIfNeeded: true) { (revealedDocumentURL, error) in 38 | if let error = error { 39 | // Handle the error appropriately 40 | print("Failed to reveal the document at URL \(inputURL) with error: '\(error)'") 41 | return 42 | } 43 | 44 | // Present the Document View Controller for the revealed URL 45 | documentBrowserViewController.presentDocument(at: revealedDocumentURL!) 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /smalltext/smalltext.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.developer.user-fonts 6 | 7 | app-usage 8 | 9 | com.apple.security.app-sandbox 10 | 11 | com.apple.security.files.user-selected.read-write 12 | 13 | com.apple.security.network.client 14 | 15 | 16 | 17 | --------------------------------------------------------------------------------