├── .gitignore ├── LICENSE.md ├── README.md ├── Roam Research.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── xcshareddata │ └── xcschemes │ │ ├── Roam Research.xcscheme │ │ └── Share to Roam.xcscheme └── xcuserdata │ └── m1guelpf.xcuserdatad │ └── xcschemes │ └── xcschememanagement.plist ├── Roam Research ├── AppDelegate.swift ├── Assets.xcassets │ ├── AccentColor.colorset │ │ └── Contents.json │ ├── AppIcon.appiconset │ │ ├── Contents.json │ │ ├── icn-1024.png │ │ ├── icn-20.png │ │ ├── icn-20@2x.png │ │ ├── icn-20@3x.png │ │ ├── icn-29.png │ │ ├── icn-29@2x.png │ │ ├── icn-29@3x.png │ │ ├── icn-40.png │ │ ├── icn-40@2x.png │ │ ├── icn-40@3x.png │ │ ├── icn-60@2x.png │ │ ├── icn-60@3x.png │ │ ├── icn-76.png │ │ ├── icn-76@2x.png │ │ └── icn-83.5@2x.png │ └── Contents.json ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard ├── Info.plist ├── Roam Research.entitlements ├── Roam ResearchRelease.entitlements ├── SceneDelegate.swift └── ViewController.swift └── Share to Roam ├── Base.lproj └── MainInterface.storyboard ├── Info.plist ├── Share to Roam.entitlements ├── Share to RoamRelease.entitlements └── ShareViewController.swift /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## User settings 6 | xcuserdata/ 7 | 8 | ## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9) 9 | *.xcscmblueprint 10 | *.xccheckout 11 | 12 | ## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4) 13 | build/ 14 | DerivedData/ 15 | *.moved-aside 16 | *.pbxuser 17 | !default.pbxuser 18 | *.mode1v3 19 | !default.mode1v3 20 | *.mode2v3 21 | !default.mode2v3 22 | *.perspectivev3 23 | !default.perspectivev3 24 | 25 | ## Obj-C/Swift specific 26 | *.hmap 27 | 28 | ## App packaging 29 | *.ipa 30 | *.dSYM.zip 31 | *.dSYM 32 | 33 | ## Playgrounds 34 | timeline.xctimeline 35 | playground.xcworkspace 36 | 37 | # Swift Package Manager 38 | # 39 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 40 | # Packages/ 41 | # Package.pins 42 | # Package.resolved 43 | # *.xcodeproj 44 | # 45 | # Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata 46 | # hence it is not needed unless you have added a package configuration file to your project 47 | # .swiftpm 48 | 49 | .build/ 50 | 51 | # CocoaPods 52 | # 53 | # We recommend against adding the Pods directory to your .gitignore. However 54 | # you should judge for yourself, the pros and cons are mentioned at: 55 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 56 | # 57 | # Pods/ 58 | # 59 | # Add this line if you want to avoid checking in source code from the Xcode workspace 60 | # *.xcworkspace 61 | 62 | # Carthage 63 | # 64 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 65 | # Carthage/Checkouts 66 | 67 | Carthage/Build/ 68 | 69 | # Accio dependency management 70 | Dependencies/ 71 | .accio/ 72 | 73 | # fastlane 74 | # 75 | # It is recommended to not store the screenshots in the git repo. 76 | # Instead, use fastlane to re-generate the screenshots whenever they are needed. 77 | # For more information about the recommended setup visit: 78 | # https://docs.fastlane.tools/best-practices/source-control/#source-control 79 | 80 | fastlane/report.xml 81 | fastlane/Preview.html 82 | fastlane/screenshots/**/*.png 83 | fastlane/test_output 84 | 85 | # Code Injection 86 | # 87 | # After new code Injection tools there's a generated folder /iOSInjectionProject 88 | # https://github.com/johnno1962/injectionforxcode 89 | 90 | iOSInjectionProject/ 91 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) Miguel Piedrafita 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Roam Research App 2 | 3 | > An iOS app for Roam Research, including a "Share to Roam" extension. 4 | 5 | This app wraps the Roam Research website in a webview, allowing you to benefit from native app features such as multitasking on iPad. It also includes a Share Sheet integration which leverages Roam's Quick Capture page to quickly share any content to your graph from the native iOS share menu. 6 | 7 | ## Installing 8 | 9 | I'm working to list the app on the App Store, but in the meantime you can [download it on Airport](https://app.airport.community/app/recvAbcGjrNK1DbWe). 10 | 11 | ## Contributing 12 | 13 | This is my first iOS app, and my first experience with Swift. There are probably much better ways to do the things I've done and, if you know them, I'd really appreciate a PR 😁 14 | 15 | Other than that, a better onboarding mechanism (an actual Swift view to select your graph instead of an alert) would be very welcome. 16 | 17 | ## License 18 | 19 | This project is open-sourced software licensed under the MIT license. See the [License file](LICENSE.md) for more information. 20 | -------------------------------------------------------------------------------- /Roam Research.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 54; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | C01F931A26BE331F004BAAAC /* ShareViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C01F931926BE331F004BAAAC /* ShareViewController.swift */; }; 11 | C01F931D26BE331F004BAAAC /* MainInterface.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = C01F931B26BE331F004BAAAC /* MainInterface.storyboard */; }; 12 | C01F932126BE331F004BAAAC /* Share to Roam.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = C01F931726BE331F004BAAAC /* Share to Roam.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; 13 | C05FA57C26BE087700AEF3B2 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C05FA57B26BE087700AEF3B2 /* AppDelegate.swift */; }; 14 | C05FA57E26BE087700AEF3B2 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C05FA57D26BE087700AEF3B2 /* SceneDelegate.swift */; }; 15 | C05FA58026BE087700AEF3B2 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C05FA57F26BE087700AEF3B2 /* ViewController.swift */; }; 16 | C05FA58326BE087700AEF3B2 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = C05FA58126BE087700AEF3B2 /* Main.storyboard */; }; 17 | C05FA58526BE087800AEF3B2 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = C05FA58426BE087800AEF3B2 /* Assets.xcassets */; }; 18 | C05FA58826BE087800AEF3B2 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = C05FA58626BE087800AEF3B2 /* LaunchScreen.storyboard */; }; 19 | /* End PBXBuildFile section */ 20 | 21 | /* Begin PBXContainerItemProxy section */ 22 | C01F931F26BE331F004BAAAC /* PBXContainerItemProxy */ = { 23 | isa = PBXContainerItemProxy; 24 | containerPortal = C05FA57026BE087700AEF3B2 /* Project object */; 25 | proxyType = 1; 26 | remoteGlobalIDString = C01F931626BE331F004BAAAC; 27 | remoteInfo = "Share to Roam"; 28 | }; 29 | /* End PBXContainerItemProxy section */ 30 | 31 | /* Begin PBXCopyFilesBuildPhase section */ 32 | C01F930D26BE272E004BAAAC /* Embed App Extensions */ = { 33 | isa = PBXCopyFilesBuildPhase; 34 | buildActionMask = 2147483647; 35 | dstPath = ""; 36 | dstSubfolderSpec = 13; 37 | files = ( 38 | C01F932126BE331F004BAAAC /* Share to Roam.appex in Embed App Extensions */, 39 | ); 40 | name = "Embed App Extensions"; 41 | runOnlyForDeploymentPostprocessing = 0; 42 | }; 43 | /* End PBXCopyFilesBuildPhase section */ 44 | 45 | /* Begin PBXFileReference section */ 46 | C01A228626BF5B9A009FBBE0 /* Roam Research.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "Roam Research.entitlements"; sourceTree = ""; }; 47 | C01A228726BF5BA7009FBBE0 /* Roam ResearchRelease.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "Roam ResearchRelease.entitlements"; sourceTree = ""; }; 48 | C01A228826BF5C06009FBBE0 /* Share to Roam.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "Share to Roam.entitlements"; sourceTree = ""; }; 49 | C01A228926BF5C14009FBBE0 /* Share to RoamRelease.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "Share to RoamRelease.entitlements"; sourceTree = ""; }; 50 | C01F931726BE331F004BAAAC /* Share to Roam.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "Share to Roam.appex"; sourceTree = BUILT_PRODUCTS_DIR; }; 51 | C01F931926BE331F004BAAAC /* ShareViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareViewController.swift; sourceTree = ""; }; 52 | C01F931C26BE331F004BAAAC /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/MainInterface.storyboard; sourceTree = ""; }; 53 | C01F931E26BE331F004BAAAC /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 54 | C036A79026BF4F1C0012F395 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; 55 | C036A79126BF51EE0012F395 /* LICENSE.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = LICENSE.md; sourceTree = ""; }; 56 | C05FA57826BE087700AEF3B2 /* Roam Research.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Roam Research.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 57 | C05FA57B26BE087700AEF3B2 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 58 | C05FA57D26BE087700AEF3B2 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; 59 | C05FA57F26BE087700AEF3B2 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 60 | C05FA58226BE087700AEF3B2 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 61 | C05FA58426BE087800AEF3B2 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 62 | C05FA58726BE087800AEF3B2 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 63 | C05FA58926BE087800AEF3B2 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 64 | /* End PBXFileReference section */ 65 | 66 | /* Begin PBXFrameworksBuildPhase section */ 67 | C01F931426BE331F004BAAAC /* Frameworks */ = { 68 | isa = PBXFrameworksBuildPhase; 69 | buildActionMask = 2147483647; 70 | files = ( 71 | ); 72 | runOnlyForDeploymentPostprocessing = 0; 73 | }; 74 | C05FA57526BE087700AEF3B2 /* Frameworks */ = { 75 | isa = PBXFrameworksBuildPhase; 76 | buildActionMask = 2147483647; 77 | files = ( 78 | ); 79 | runOnlyForDeploymentPostprocessing = 0; 80 | }; 81 | /* End PBXFrameworksBuildPhase section */ 82 | 83 | /* Begin PBXGroup section */ 84 | C01F931826BE331F004BAAAC /* Share to Roam */ = { 85 | isa = PBXGroup; 86 | children = ( 87 | C01A228926BF5C14009FBBE0 /* Share to RoamRelease.entitlements */, 88 | C01A228826BF5C06009FBBE0 /* Share to Roam.entitlements */, 89 | C01F931926BE331F004BAAAC /* ShareViewController.swift */, 90 | C01F931B26BE331F004BAAAC /* MainInterface.storyboard */, 91 | C01F931E26BE331F004BAAAC /* Info.plist */, 92 | ); 93 | path = "Share to Roam"; 94 | sourceTree = ""; 95 | }; 96 | C05FA56F26BE087700AEF3B2 = { 97 | isa = PBXGroup; 98 | children = ( 99 | C036A79126BF51EE0012F395 /* LICENSE.md */, 100 | C036A79026BF4F1C0012F395 /* README.md */, 101 | C05FA57A26BE087700AEF3B2 /* Roam Research */, 102 | C01F931826BE331F004BAAAC /* Share to Roam */, 103 | C05FA57926BE087700AEF3B2 /* Products */, 104 | ); 105 | sourceTree = ""; 106 | }; 107 | C05FA57926BE087700AEF3B2 /* Products */ = { 108 | isa = PBXGroup; 109 | children = ( 110 | C05FA57826BE087700AEF3B2 /* Roam Research.app */, 111 | C01F931726BE331F004BAAAC /* Share to Roam.appex */, 112 | ); 113 | name = Products; 114 | sourceTree = ""; 115 | }; 116 | C05FA57A26BE087700AEF3B2 /* Roam Research */ = { 117 | isa = PBXGroup; 118 | children = ( 119 | C01A228726BF5BA7009FBBE0 /* Roam ResearchRelease.entitlements */, 120 | C01A228626BF5B9A009FBBE0 /* Roam Research.entitlements */, 121 | C05FA57B26BE087700AEF3B2 /* AppDelegate.swift */, 122 | C05FA57D26BE087700AEF3B2 /* SceneDelegate.swift */, 123 | C05FA57F26BE087700AEF3B2 /* ViewController.swift */, 124 | C05FA58126BE087700AEF3B2 /* Main.storyboard */, 125 | C05FA58426BE087800AEF3B2 /* Assets.xcassets */, 126 | C05FA58626BE087800AEF3B2 /* LaunchScreen.storyboard */, 127 | C05FA58926BE087800AEF3B2 /* Info.plist */, 128 | ); 129 | path = "Roam Research"; 130 | sourceTree = ""; 131 | }; 132 | /* End PBXGroup section */ 133 | 134 | /* Begin PBXNativeTarget section */ 135 | C01F931626BE331F004BAAAC /* Share to Roam */ = { 136 | isa = PBXNativeTarget; 137 | buildConfigurationList = C01F932226BE331F004BAAAC /* Build configuration list for PBXNativeTarget "Share to Roam" */; 138 | buildPhases = ( 139 | C01F931326BE331F004BAAAC /* Sources */, 140 | C01F931426BE331F004BAAAC /* Frameworks */, 141 | C01F931526BE331F004BAAAC /* Resources */, 142 | ); 143 | buildRules = ( 144 | ); 145 | dependencies = ( 146 | ); 147 | name = "Share to Roam"; 148 | productName = "Share to Roam"; 149 | productReference = C01F931726BE331F004BAAAC /* Share to Roam.appex */; 150 | productType = "com.apple.product-type.app-extension"; 151 | }; 152 | C05FA57726BE087700AEF3B2 /* Roam Research */ = { 153 | isa = PBXNativeTarget; 154 | buildConfigurationList = C05FA58C26BE087800AEF3B2 /* Build configuration list for PBXNativeTarget "Roam Research" */; 155 | buildPhases = ( 156 | C05FA57426BE087700AEF3B2 /* Sources */, 157 | C05FA57526BE087700AEF3B2 /* Frameworks */, 158 | C05FA57626BE087700AEF3B2 /* Resources */, 159 | C01F930D26BE272E004BAAAC /* Embed App Extensions */, 160 | ); 161 | buildRules = ( 162 | ); 163 | dependencies = ( 164 | C01F932026BE331F004BAAAC /* PBXTargetDependency */, 165 | ); 166 | name = "Roam Research"; 167 | productName = "Roam Research"; 168 | productReference = C05FA57826BE087700AEF3B2 /* Roam Research.app */; 169 | productType = "com.apple.product-type.application"; 170 | }; 171 | /* End PBXNativeTarget section */ 172 | 173 | /* Begin PBXProject section */ 174 | C05FA57026BE087700AEF3B2 /* Project object */ = { 175 | isa = PBXProject; 176 | attributes = { 177 | BuildIndependentTargetsInParallel = 1; 178 | LastSwiftUpdateCheck = 1300; 179 | LastUpgradeCheck = 1300; 180 | TargetAttributes = { 181 | C01F931626BE331F004BAAAC = { 182 | CreatedOnToolsVersion = 13.0; 183 | }; 184 | C05FA57726BE087700AEF3B2 = { 185 | CreatedOnToolsVersion = 13.0; 186 | }; 187 | }; 188 | }; 189 | buildConfigurationList = C05FA57326BE087700AEF3B2 /* Build configuration list for PBXProject "Roam Research" */; 190 | compatibilityVersion = "Xcode 12.0"; 191 | developmentRegion = en; 192 | hasScannedForEncodings = 0; 193 | knownRegions = ( 194 | en, 195 | Base, 196 | ); 197 | mainGroup = C05FA56F26BE087700AEF3B2; 198 | productRefGroup = C05FA57926BE087700AEF3B2 /* Products */; 199 | projectDirPath = ""; 200 | projectRoot = ""; 201 | targets = ( 202 | C05FA57726BE087700AEF3B2 /* Roam Research */, 203 | C01F931626BE331F004BAAAC /* Share to Roam */, 204 | ); 205 | }; 206 | /* End PBXProject section */ 207 | 208 | /* Begin PBXResourcesBuildPhase section */ 209 | C01F931526BE331F004BAAAC /* Resources */ = { 210 | isa = PBXResourcesBuildPhase; 211 | buildActionMask = 2147483647; 212 | files = ( 213 | C01F931D26BE331F004BAAAC /* MainInterface.storyboard in Resources */, 214 | ); 215 | runOnlyForDeploymentPostprocessing = 0; 216 | }; 217 | C05FA57626BE087700AEF3B2 /* Resources */ = { 218 | isa = PBXResourcesBuildPhase; 219 | buildActionMask = 2147483647; 220 | files = ( 221 | C05FA58826BE087800AEF3B2 /* LaunchScreen.storyboard in Resources */, 222 | C05FA58526BE087800AEF3B2 /* Assets.xcassets in Resources */, 223 | C05FA58326BE087700AEF3B2 /* Main.storyboard in Resources */, 224 | ); 225 | runOnlyForDeploymentPostprocessing = 0; 226 | }; 227 | /* End PBXResourcesBuildPhase section */ 228 | 229 | /* Begin PBXSourcesBuildPhase section */ 230 | C01F931326BE331F004BAAAC /* Sources */ = { 231 | isa = PBXSourcesBuildPhase; 232 | buildActionMask = 2147483647; 233 | files = ( 234 | C01F931A26BE331F004BAAAC /* ShareViewController.swift in Sources */, 235 | ); 236 | runOnlyForDeploymentPostprocessing = 0; 237 | }; 238 | C05FA57426BE087700AEF3B2 /* Sources */ = { 239 | isa = PBXSourcesBuildPhase; 240 | buildActionMask = 2147483647; 241 | files = ( 242 | C05FA58026BE087700AEF3B2 /* ViewController.swift in Sources */, 243 | C05FA57C26BE087700AEF3B2 /* AppDelegate.swift in Sources */, 244 | C05FA57E26BE087700AEF3B2 /* SceneDelegate.swift in Sources */, 245 | ); 246 | runOnlyForDeploymentPostprocessing = 0; 247 | }; 248 | /* End PBXSourcesBuildPhase section */ 249 | 250 | /* Begin PBXTargetDependency section */ 251 | C01F932026BE331F004BAAAC /* PBXTargetDependency */ = { 252 | isa = PBXTargetDependency; 253 | target = C01F931626BE331F004BAAAC /* Share to Roam */; 254 | targetProxy = C01F931F26BE331F004BAAAC /* PBXContainerItemProxy */; 255 | }; 256 | /* End PBXTargetDependency section */ 257 | 258 | /* Begin PBXVariantGroup section */ 259 | C01F931B26BE331F004BAAAC /* MainInterface.storyboard */ = { 260 | isa = PBXVariantGroup; 261 | children = ( 262 | C01F931C26BE331F004BAAAC /* Base */, 263 | ); 264 | name = MainInterface.storyboard; 265 | sourceTree = ""; 266 | }; 267 | C05FA58126BE087700AEF3B2 /* Main.storyboard */ = { 268 | isa = PBXVariantGroup; 269 | children = ( 270 | C05FA58226BE087700AEF3B2 /* Base */, 271 | ); 272 | name = Main.storyboard; 273 | sourceTree = ""; 274 | }; 275 | C05FA58626BE087800AEF3B2 /* LaunchScreen.storyboard */ = { 276 | isa = PBXVariantGroup; 277 | children = ( 278 | C05FA58726BE087800AEF3B2 /* Base */, 279 | ); 280 | name = LaunchScreen.storyboard; 281 | sourceTree = ""; 282 | }; 283 | /* End PBXVariantGroup section */ 284 | 285 | /* Begin XCBuildConfiguration section */ 286 | C01F932326BE331F004BAAAC /* Debug */ = { 287 | isa = XCBuildConfiguration; 288 | buildSettings = { 289 | CODE_SIGN_ENTITLEMENTS = "Share to Roam/Share to Roam.entitlements"; 290 | CODE_SIGN_STYLE = Automatic; 291 | CURRENT_PROJECT_VERSION = 3; 292 | DEVELOPMENT_TEAM = LR4RJT6586; 293 | GENERATE_INFOPLIST_FILE = YES; 294 | INFOPLIST_FILE = "Share to Roam/Info.plist"; 295 | INFOPLIST_KEY_CFBundleDisplayName = "Share to Roam"; 296 | INFOPLIST_KEY_NSHumanReadableCopyright = ""; 297 | LD_RUNPATH_SEARCH_PATHS = ( 298 | "$(inherited)", 299 | "@executable_path/Frameworks", 300 | "@executable_path/../../Frameworks", 301 | ); 302 | MARKETING_VERSION = 1.0; 303 | PRODUCT_BUNDLE_IDENTIFIER = me.m1guelpf.RoamResearch.RoamShare; 304 | PRODUCT_NAME = "$(TARGET_NAME)"; 305 | SKIP_INSTALL = YES; 306 | SWIFT_EMIT_LOC_STRINGS = YES; 307 | SWIFT_VERSION = 5.0; 308 | TARGETED_DEVICE_FAMILY = "1,2"; 309 | }; 310 | name = Debug; 311 | }; 312 | C01F932426BE331F004BAAAC /* Release */ = { 313 | isa = XCBuildConfiguration; 314 | buildSettings = { 315 | CODE_SIGN_ENTITLEMENTS = "Share to Roam/Share to RoamRelease.entitlements"; 316 | CODE_SIGN_STYLE = Automatic; 317 | CURRENT_PROJECT_VERSION = 3; 318 | DEVELOPMENT_TEAM = LR4RJT6586; 319 | GENERATE_INFOPLIST_FILE = YES; 320 | INFOPLIST_FILE = "Share to Roam/Info.plist"; 321 | INFOPLIST_KEY_CFBundleDisplayName = "Share to Roam"; 322 | INFOPLIST_KEY_NSHumanReadableCopyright = ""; 323 | LD_RUNPATH_SEARCH_PATHS = ( 324 | "$(inherited)", 325 | "@executable_path/Frameworks", 326 | "@executable_path/../../Frameworks", 327 | ); 328 | MARKETING_VERSION = 1.0; 329 | PRODUCT_BUNDLE_IDENTIFIER = me.m1guelpf.RoamResearch.RoamShare; 330 | PRODUCT_NAME = "$(TARGET_NAME)"; 331 | SKIP_INSTALL = YES; 332 | SWIFT_EMIT_LOC_STRINGS = YES; 333 | SWIFT_VERSION = 5.0; 334 | TARGETED_DEVICE_FAMILY = "1,2"; 335 | }; 336 | name = Release; 337 | }; 338 | C05FA58A26BE087800AEF3B2 /* Debug */ = { 339 | isa = XCBuildConfiguration; 340 | buildSettings = { 341 | ALWAYS_SEARCH_USER_PATHS = NO; 342 | CLANG_ANALYZER_NONNULL = YES; 343 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 344 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; 345 | CLANG_CXX_LIBRARY = "libc++"; 346 | CLANG_ENABLE_MODULES = YES; 347 | CLANG_ENABLE_OBJC_ARC = YES; 348 | CLANG_ENABLE_OBJC_WEAK = YES; 349 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 350 | CLANG_WARN_BOOL_CONVERSION = YES; 351 | CLANG_WARN_COMMA = YES; 352 | CLANG_WARN_CONSTANT_CONVERSION = YES; 353 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 354 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 355 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 356 | CLANG_WARN_EMPTY_BODY = YES; 357 | CLANG_WARN_ENUM_CONVERSION = YES; 358 | CLANG_WARN_INFINITE_RECURSION = YES; 359 | CLANG_WARN_INT_CONVERSION = YES; 360 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 361 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 362 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 363 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 364 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 365 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 366 | CLANG_WARN_STRICT_PROTOTYPES = YES; 367 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 368 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 369 | CLANG_WARN_UNREACHABLE_CODE = YES; 370 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 371 | COPY_PHASE_STRIP = NO; 372 | DEBUG_INFORMATION_FORMAT = dwarf; 373 | ENABLE_STRICT_OBJC_MSGSEND = YES; 374 | ENABLE_TESTABILITY = YES; 375 | GCC_C_LANGUAGE_STANDARD = gnu11; 376 | GCC_DYNAMIC_NO_PIC = NO; 377 | GCC_NO_COMMON_BLOCKS = YES; 378 | GCC_OPTIMIZATION_LEVEL = 0; 379 | GCC_PREPROCESSOR_DEFINITIONS = ( 380 | "DEBUG=1", 381 | "$(inherited)", 382 | ); 383 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 384 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 385 | GCC_WARN_UNDECLARED_SELECTOR = YES; 386 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 387 | GCC_WARN_UNUSED_FUNCTION = YES; 388 | GCC_WARN_UNUSED_VARIABLE = YES; 389 | IPHONEOS_DEPLOYMENT_TARGET = 14.0; 390 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 391 | MTL_FAST_MATH = YES; 392 | ONLY_ACTIVE_ARCH = YES; 393 | SDKROOT = iphoneos; 394 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 395 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 396 | }; 397 | name = Debug; 398 | }; 399 | C05FA58B26BE087800AEF3B2 /* Release */ = { 400 | isa = XCBuildConfiguration; 401 | buildSettings = { 402 | ALWAYS_SEARCH_USER_PATHS = NO; 403 | CLANG_ANALYZER_NONNULL = YES; 404 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 405 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; 406 | CLANG_CXX_LIBRARY = "libc++"; 407 | CLANG_ENABLE_MODULES = YES; 408 | CLANG_ENABLE_OBJC_ARC = YES; 409 | CLANG_ENABLE_OBJC_WEAK = YES; 410 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 411 | CLANG_WARN_BOOL_CONVERSION = YES; 412 | CLANG_WARN_COMMA = YES; 413 | CLANG_WARN_CONSTANT_CONVERSION = YES; 414 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 415 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 416 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 417 | CLANG_WARN_EMPTY_BODY = YES; 418 | CLANG_WARN_ENUM_CONVERSION = YES; 419 | CLANG_WARN_INFINITE_RECURSION = YES; 420 | CLANG_WARN_INT_CONVERSION = YES; 421 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 422 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 423 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 424 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 425 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 426 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 427 | CLANG_WARN_STRICT_PROTOTYPES = YES; 428 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 429 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 430 | CLANG_WARN_UNREACHABLE_CODE = YES; 431 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 432 | COPY_PHASE_STRIP = NO; 433 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 434 | ENABLE_NS_ASSERTIONS = NO; 435 | ENABLE_STRICT_OBJC_MSGSEND = YES; 436 | GCC_C_LANGUAGE_STANDARD = gnu11; 437 | GCC_NO_COMMON_BLOCKS = YES; 438 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 439 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 440 | GCC_WARN_UNDECLARED_SELECTOR = YES; 441 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 442 | GCC_WARN_UNUSED_FUNCTION = YES; 443 | GCC_WARN_UNUSED_VARIABLE = YES; 444 | IPHONEOS_DEPLOYMENT_TARGET = 14.0; 445 | MTL_ENABLE_DEBUG_INFO = NO; 446 | MTL_FAST_MATH = YES; 447 | SDKROOT = iphoneos; 448 | SWIFT_COMPILATION_MODE = wholemodule; 449 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 450 | VALIDATE_PRODUCT = YES; 451 | }; 452 | name = Release; 453 | }; 454 | C05FA58D26BE087800AEF3B2 /* Debug */ = { 455 | isa = XCBuildConfiguration; 456 | buildSettings = { 457 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 458 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 459 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 460 | ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = NO; 461 | CODE_SIGN_ENTITLEMENTS = "Roam Research/Roam Research.entitlements"; 462 | CODE_SIGN_STYLE = Automatic; 463 | CURRENT_PROJECT_VERSION = 3; 464 | DEVELOPMENT_TEAM = LR4RJT6586; 465 | GENERATE_INFOPLIST_FILE = YES; 466 | INFOPLIST_FILE = "Roam Research/Info.plist"; 467 | INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; 468 | INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; 469 | INFOPLIST_KEY_UIMainStoryboardFile = Main; 470 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 471 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 472 | LD_RUNPATH_SEARCH_PATHS = ( 473 | "$(inherited)", 474 | "@executable_path/Frameworks", 475 | ); 476 | MARKETING_VERSION = 1.0; 477 | PRODUCT_BUNDLE_IDENTIFIER = me.m1guelpf.RoamResearch; 478 | PRODUCT_NAME = "$(TARGET_NAME)"; 479 | SWIFT_EMIT_LOC_STRINGS = YES; 480 | SWIFT_VERSION = 5.0; 481 | TARGETED_DEVICE_FAMILY = "1,2"; 482 | }; 483 | name = Debug; 484 | }; 485 | C05FA58E26BE087800AEF3B2 /* Release */ = { 486 | isa = XCBuildConfiguration; 487 | buildSettings = { 488 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 489 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 490 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 491 | ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = NO; 492 | CODE_SIGN_ENTITLEMENTS = "Roam Research/Roam ResearchRelease.entitlements"; 493 | CODE_SIGN_STYLE = Automatic; 494 | CURRENT_PROJECT_VERSION = 3; 495 | DEVELOPMENT_TEAM = LR4RJT6586; 496 | GENERATE_INFOPLIST_FILE = YES; 497 | INFOPLIST_FILE = "Roam Research/Info.plist"; 498 | INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; 499 | INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; 500 | INFOPLIST_KEY_UIMainStoryboardFile = Main; 501 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 502 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 503 | LD_RUNPATH_SEARCH_PATHS = ( 504 | "$(inherited)", 505 | "@executable_path/Frameworks", 506 | ); 507 | MARKETING_VERSION = 1.0; 508 | PRODUCT_BUNDLE_IDENTIFIER = me.m1guelpf.RoamResearch; 509 | PRODUCT_NAME = "$(TARGET_NAME)"; 510 | SWIFT_EMIT_LOC_STRINGS = YES; 511 | SWIFT_VERSION = 5.0; 512 | TARGETED_DEVICE_FAMILY = "1,2"; 513 | }; 514 | name = Release; 515 | }; 516 | /* End XCBuildConfiguration section */ 517 | 518 | /* Begin XCConfigurationList section */ 519 | C01F932226BE331F004BAAAC /* Build configuration list for PBXNativeTarget "Share to Roam" */ = { 520 | isa = XCConfigurationList; 521 | buildConfigurations = ( 522 | C01F932326BE331F004BAAAC /* Debug */, 523 | C01F932426BE331F004BAAAC /* Release */, 524 | ); 525 | defaultConfigurationIsVisible = 0; 526 | defaultConfigurationName = Release; 527 | }; 528 | C05FA57326BE087700AEF3B2 /* Build configuration list for PBXProject "Roam Research" */ = { 529 | isa = XCConfigurationList; 530 | buildConfigurations = ( 531 | C05FA58A26BE087800AEF3B2 /* Debug */, 532 | C05FA58B26BE087800AEF3B2 /* Release */, 533 | ); 534 | defaultConfigurationIsVisible = 0; 535 | defaultConfigurationName = Release; 536 | }; 537 | C05FA58C26BE087800AEF3B2 /* Build configuration list for PBXNativeTarget "Roam Research" */ = { 538 | isa = XCConfigurationList; 539 | buildConfigurations = ( 540 | C05FA58D26BE087800AEF3B2 /* Debug */, 541 | C05FA58E26BE087800AEF3B2 /* Release */, 542 | ); 543 | defaultConfigurationIsVisible = 0; 544 | defaultConfigurationName = Release; 545 | }; 546 | /* End XCConfigurationList section */ 547 | }; 548 | rootObject = C05FA57026BE087700AEF3B2 /* Project object */; 549 | } 550 | -------------------------------------------------------------------------------- /Roam Research.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Roam Research.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Roam Research.xcodeproj/xcshareddata/xcschemes/Roam Research.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 43 | 45 | 51 | 52 | 53 | 54 | 60 | 62 | 68 | 69 | 70 | 71 | 73 | 74 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /Roam Research.xcodeproj/xcshareddata/xcschemes/Share to Roam.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 6 | 9 | 10 | 16 | 22 | 23 | 24 | 30 | 36 | 37 | 38 | 39 | 40 | 45 | 46 | 47 | 48 | 60 | 61 | 67 | 68 | 69 | 70 | 77 | 79 | 85 | 86 | 87 | 88 | 90 | 91 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /Roam Research.xcodeproj/xcuserdata/m1guelpf.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | Roam Research.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | Share to Roam.xcscheme_^#shared#^_ 13 | 14 | orderHint 15 | 1 16 | 17 | 18 | SuppressBuildableAutocreation 19 | 20 | C01F930126BE272E004BAAAC 21 | 22 | primary 23 | 24 | 25 | C05FA57726BE087700AEF3B2 26 | 27 | primary 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /Roam Research/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // Roam Research 4 | // 5 | // Created by Miguel Piedrafita on 7/8/21. 6 | // 7 | 8 | import UIKit 9 | 10 | @main 11 | class AppDelegate: UIResponder, UIApplicationDelegate { 12 | 13 | 14 | 15 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 16 | // Override point for customization after application launch. 17 | return true 18 | } 19 | 20 | // MARK: UISceneSession Lifecycle 21 | 22 | func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { 23 | // Called when a new scene session is being created. 24 | // Use this method to select a configuration to create the new scene with. 25 | return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) 26 | } 27 | 28 | func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) { 29 | // Called when the user discards a scene session. 30 | // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. 31 | // Use this method to release any resources that were specific to the discarded scenes, as they will not return. 32 | } 33 | 34 | 35 | } 36 | 37 | -------------------------------------------------------------------------------- /Roam Research/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 | -------------------------------------------------------------------------------- /Roam Research/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "icn-20@2x.png", 5 | "idiom" : "iphone", 6 | "scale" : "2x", 7 | "size" : "20x20" 8 | }, 9 | { 10 | "filename" : "icn-20@3x.png", 11 | "idiom" : "iphone", 12 | "scale" : "3x", 13 | "size" : "20x20" 14 | }, 15 | { 16 | "filename" : "icn-29@2x.png", 17 | "idiom" : "iphone", 18 | "scale" : "2x", 19 | "size" : "29x29" 20 | }, 21 | { 22 | "filename" : "icn-29@3x.png", 23 | "idiom" : "iphone", 24 | "scale" : "3x", 25 | "size" : "29x29" 26 | }, 27 | { 28 | "filename" : "icn-40@2x.png", 29 | "idiom" : "iphone", 30 | "scale" : "2x", 31 | "size" : "40x40" 32 | }, 33 | { 34 | "filename" : "icn-40@3x.png", 35 | "idiom" : "iphone", 36 | "scale" : "3x", 37 | "size" : "40x40" 38 | }, 39 | { 40 | "filename" : "icn-60@2x.png", 41 | "idiom" : "iphone", 42 | "scale" : "2x", 43 | "size" : "60x60" 44 | }, 45 | { 46 | "filename" : "icn-60@3x.png", 47 | "idiom" : "iphone", 48 | "scale" : "3x", 49 | "size" : "60x60" 50 | }, 51 | { 52 | "filename" : "icn-20.png", 53 | "idiom" : "ipad", 54 | "scale" : "1x", 55 | "size" : "20x20" 56 | }, 57 | { 58 | "filename" : "icn-20@2x.png", 59 | "idiom" : "ipad", 60 | "scale" : "2x", 61 | "size" : "20x20" 62 | }, 63 | { 64 | "filename" : "icn-29.png", 65 | "idiom" : "ipad", 66 | "scale" : "1x", 67 | "size" : "29x29" 68 | }, 69 | { 70 | "filename" : "icn-29@2x.png", 71 | "idiom" : "ipad", 72 | "scale" : "2x", 73 | "size" : "29x29" 74 | }, 75 | { 76 | "filename" : "icn-40.png", 77 | "idiom" : "ipad", 78 | "scale" : "1x", 79 | "size" : "40x40" 80 | }, 81 | { 82 | "filename" : "icn-40@2x.png", 83 | "idiom" : "ipad", 84 | "scale" : "2x", 85 | "size" : "40x40" 86 | }, 87 | { 88 | "filename" : "icn-76.png", 89 | "idiom" : "ipad", 90 | "scale" : "1x", 91 | "size" : "76x76" 92 | }, 93 | { 94 | "filename" : "icn-76@2x.png", 95 | "idiom" : "ipad", 96 | "scale" : "2x", 97 | "size" : "76x76" 98 | }, 99 | { 100 | "filename" : "icn-83.5@2x.png", 101 | "idiom" : "ipad", 102 | "scale" : "2x", 103 | "size" : "83.5x83.5" 104 | }, 105 | { 106 | "filename" : "icn-1024.png", 107 | "idiom" : "ios-marketing", 108 | "scale" : "1x", 109 | "size" : "1024x1024" 110 | } 111 | ], 112 | "info" : { 113 | "author" : "xcode", 114 | "version" : 1 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /Roam Research/Assets.xcassets/AppIcon.appiconset/icn-1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m1guelpf/roam-app/55cb126e82867202d46750d1fe2616596f73efb7/Roam Research/Assets.xcassets/AppIcon.appiconset/icn-1024.png -------------------------------------------------------------------------------- /Roam Research/Assets.xcassets/AppIcon.appiconset/icn-20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m1guelpf/roam-app/55cb126e82867202d46750d1fe2616596f73efb7/Roam Research/Assets.xcassets/AppIcon.appiconset/icn-20.png -------------------------------------------------------------------------------- /Roam Research/Assets.xcassets/AppIcon.appiconset/icn-20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m1guelpf/roam-app/55cb126e82867202d46750d1fe2616596f73efb7/Roam Research/Assets.xcassets/AppIcon.appiconset/icn-20@2x.png -------------------------------------------------------------------------------- /Roam Research/Assets.xcassets/AppIcon.appiconset/icn-20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m1guelpf/roam-app/55cb126e82867202d46750d1fe2616596f73efb7/Roam Research/Assets.xcassets/AppIcon.appiconset/icn-20@3x.png -------------------------------------------------------------------------------- /Roam Research/Assets.xcassets/AppIcon.appiconset/icn-29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m1guelpf/roam-app/55cb126e82867202d46750d1fe2616596f73efb7/Roam Research/Assets.xcassets/AppIcon.appiconset/icn-29.png -------------------------------------------------------------------------------- /Roam Research/Assets.xcassets/AppIcon.appiconset/icn-29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m1guelpf/roam-app/55cb126e82867202d46750d1fe2616596f73efb7/Roam Research/Assets.xcassets/AppIcon.appiconset/icn-29@2x.png -------------------------------------------------------------------------------- /Roam Research/Assets.xcassets/AppIcon.appiconset/icn-29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m1guelpf/roam-app/55cb126e82867202d46750d1fe2616596f73efb7/Roam Research/Assets.xcassets/AppIcon.appiconset/icn-29@3x.png -------------------------------------------------------------------------------- /Roam Research/Assets.xcassets/AppIcon.appiconset/icn-40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m1guelpf/roam-app/55cb126e82867202d46750d1fe2616596f73efb7/Roam Research/Assets.xcassets/AppIcon.appiconset/icn-40.png -------------------------------------------------------------------------------- /Roam Research/Assets.xcassets/AppIcon.appiconset/icn-40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m1guelpf/roam-app/55cb126e82867202d46750d1fe2616596f73efb7/Roam Research/Assets.xcassets/AppIcon.appiconset/icn-40@2x.png -------------------------------------------------------------------------------- /Roam Research/Assets.xcassets/AppIcon.appiconset/icn-40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m1guelpf/roam-app/55cb126e82867202d46750d1fe2616596f73efb7/Roam Research/Assets.xcassets/AppIcon.appiconset/icn-40@3x.png -------------------------------------------------------------------------------- /Roam Research/Assets.xcassets/AppIcon.appiconset/icn-60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m1guelpf/roam-app/55cb126e82867202d46750d1fe2616596f73efb7/Roam Research/Assets.xcassets/AppIcon.appiconset/icn-60@2x.png -------------------------------------------------------------------------------- /Roam Research/Assets.xcassets/AppIcon.appiconset/icn-60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m1guelpf/roam-app/55cb126e82867202d46750d1fe2616596f73efb7/Roam Research/Assets.xcassets/AppIcon.appiconset/icn-60@3x.png -------------------------------------------------------------------------------- /Roam Research/Assets.xcassets/AppIcon.appiconset/icn-76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m1guelpf/roam-app/55cb126e82867202d46750d1fe2616596f73efb7/Roam Research/Assets.xcassets/AppIcon.appiconset/icn-76.png -------------------------------------------------------------------------------- /Roam Research/Assets.xcassets/AppIcon.appiconset/icn-76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m1guelpf/roam-app/55cb126e82867202d46750d1fe2616596f73efb7/Roam Research/Assets.xcassets/AppIcon.appiconset/icn-76@2x.png -------------------------------------------------------------------------------- /Roam Research/Assets.xcassets/AppIcon.appiconset/icn-83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m1guelpf/roam-app/55cb126e82867202d46750d1fe2616596f73efb7/Roam Research/Assets.xcassets/AppIcon.appiconset/icn-83.5@2x.png -------------------------------------------------------------------------------- /Roam Research/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Roam Research/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 | -------------------------------------------------------------------------------- /Roam Research/Base.lproj/Main.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 | -------------------------------------------------------------------------------- /Roam Research/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDisplayName 6 | Roam Research 7 | UIApplicationSceneManifest 8 | 9 | UIApplicationSupportsMultipleScenes 10 | 11 | UISceneConfigurations 12 | 13 | UIWindowSceneSessionRoleApplication 14 | 15 | 16 | UISceneConfigurationName 17 | Default Configuration 18 | UISceneDelegateClassName 19 | $(PRODUCT_MODULE_NAME).SceneDelegate 20 | UISceneStoryboardFile 21 | Main 22 | 23 | 24 | 25 | 26 | UISupportedInterfaceOrientations 27 | 28 | UIInterfaceOrientationPortrait 29 | UIInterfaceOrientationPortraitUpsideDown 30 | UIInterfaceOrientationLandscapeLeft 31 | UIInterfaceOrientationLandscapeRight 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /Roam Research/Roam Research.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.application-groups 6 | 7 | group.me.m1guelpf.RoamResearch 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Roam Research/Roam ResearchRelease.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.application-groups 6 | 7 | group.me.m1guelpf.RoamResearch 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Roam Research/SceneDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SceneDelegate.swift 3 | // Roam Research 4 | // 5 | // Created by Miguel Piedrafita on 7/8/21. 6 | // 7 | 8 | import UIKit 9 | 10 | class SceneDelegate: UIResponder, UIWindowSceneDelegate { 11 | 12 | var window: UIWindow? 13 | 14 | 15 | func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { 16 | // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`. 17 | // If using a storyboard, the `window` property will automatically be initialized and attached to the scene. 18 | // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead). 19 | guard let _ = (scene as? UIWindowScene) else { return } 20 | } 21 | 22 | func sceneDidDisconnect(_ scene: UIScene) { 23 | // Called as the scene is being released by the system. 24 | // This occurs shortly after the scene enters the background, or when its session is discarded. 25 | // Release any resources associated with this scene that can be re-created the next time the scene connects. 26 | // The scene may re-connect later, as its session was not necessarily discarded (see `application:didDiscardSceneSessions` instead). 27 | } 28 | 29 | func sceneDidBecomeActive(_ scene: UIScene) { 30 | // Called when the scene has moved from an inactive state to an active state. 31 | // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive. 32 | } 33 | 34 | func sceneWillResignActive(_ scene: UIScene) { 35 | // Called when the scene will move from an active state to an inactive state. 36 | // This may occur due to temporary interruptions (ex. an incoming phone call). 37 | } 38 | 39 | func sceneWillEnterForeground(_ scene: UIScene) { 40 | // Called as the scene transitions from the background to the foreground. 41 | // Use this method to undo the changes made on entering the background. 42 | } 43 | 44 | func sceneDidEnterBackground(_ scene: UIScene) { 45 | // Called as the scene transitions from the foreground to the background. 46 | // Use this method to save data, release shared resources, and store enough scene-specific state information 47 | // to restore the scene back to its current state. 48 | } 49 | 50 | 51 | } 52 | 53 | -------------------------------------------------------------------------------- /Roam Research/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // Roam Research 4 | // 5 | // Created by Miguel Piedrafita on 7/8/21. 6 | // 7 | 8 | import UIKit 9 | import WebKit 10 | 11 | class ViewController: UIViewController { 12 | 13 | let userDefaults: UserDefaults = UserDefaults.init(suiteName: "group.me.m1guelpf.RoamResearch")! 14 | 15 | override func viewDidLoad() { 16 | super.viewDidLoad() 17 | 18 | let subgraphSlug = userDefaults.value(forKey: "subgraphSlug") as? String? 19 | 20 | if (subgraphSlug ?? nil) != nil { 21 | loadWebView(subgraphSlug: subgraphSlug!!) 22 | } 23 | } 24 | 25 | override func viewDidAppear(_ animated: Bool) { 26 | let subgraphSlug = userDefaults.value(forKey: "subgraphSlug") as? String? 27 | 28 | if (subgraphSlug ?? nil) != nil { 29 | return 30 | } 31 | 32 | let alertController = UIAlertController(title: "Roam Graph", message: "Enter the slug of your Roam graph", preferredStyle: .alert) 33 | 34 | alertController.addTextField { (textField) in textField.placeholder = "m1guelpf" } 35 | 36 | alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: { [self] (action) in 37 | if let text = alertController.textFields?.first?.text { 38 | userDefaults.set(text as String?, forKey: "subgraphSlug") 39 | loadWebView(subgraphSlug: text) 40 | } else { 41 | self.closeApp() 42 | } 43 | })) 44 | 45 | present(alertController, animated: true, completion: nil) 46 | } 47 | 48 | func loadWebView(subgraphSlug: String) { 49 | let config = WKWebViewConfiguration() 50 | let script = WKUserScript(source: "document.body.classList.add('roam-app')", injectionTime: .atDocumentEnd, forMainFrameOnly: true) 51 | config.userContentController.addUserScript(script) 52 | 53 | let webView = WKWebView(frame: view.frame, configuration: config) 54 | webView.navigationDelegate = self 55 | webView.uiDelegate = self 56 | webView.allowsBackForwardNavigationGestures = true 57 | webView.autoresizingMask = [.flexibleWidth, .flexibleHeight] 58 | view.addSubview(webView) 59 | 60 | let url = URL(string: "https://roamresearch.com/#/app/\(subgraphSlug)")! 61 | let request = URLRequest(url: url) 62 | webView.load(request) 63 | } 64 | 65 | func closeApp() { 66 | UIControl().sendAction(#selector(URLSessionTask.suspend), to: UIApplication.shared, for: nil) 67 | DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(1), execute: { 68 | exit(EXIT_SUCCESS) 69 | }) 70 | } 71 | } 72 | 73 | // Handler for external links & loading errors 74 | extension ViewController: WKNavigationDelegate { 75 | // Open external links on either their specific apps or Safari 76 | func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) { 77 | if navigationAction.navigationType == .linkActivated { 78 | if let url = navigationAction.request.url, 79 | UIApplication.shared.canOpenURL(url) { 80 | UIApplication.shared.open(url) 81 | decisionHandler(.cancel) 82 | } else { 83 | // Open in web view 84 | decisionHandler(.allow) 85 | } 86 | } else { 87 | // other navigation type, such as reload, back or forward buttons 88 | decisionHandler(.allow) 89 | } 90 | } 91 | 92 | // Close app if loading Roam fails 93 | func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) { 94 | let alertController = UIAlertController(title: nil, message: error.localizedDescription, preferredStyle: .alert) 95 | alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: { (action) in self.closeApp() })) 96 | 97 | present(alertController, animated: true, completion: nil) 98 | } 99 | } 100 | 101 | // Render alert(), confirm() & dialog() 102 | extension ViewController: WKUIDelegate { 103 | func webView(_ webView: WKWebView, runJavaScriptAlertPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping () -> Void) 104 | { 105 | let alertController = UIAlertController(title: nil, message: message, preferredStyle: .alert) 106 | alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: { (action) in completionHandler() })) 107 | 108 | present(alertController, animated: true, completion: nil) 109 | } 110 | 111 | func webView(_ webView: WKWebView, runJavaScriptConfirmPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping (Bool) -> Void) { 112 | 113 | let alertController = UIAlertController(title: nil, message: message, preferredStyle: .alert) 114 | 115 | alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: { (action) in completionHandler(true) })) 116 | 117 | alertController.addAction(UIAlertAction(title: "Cancel", style: .default, handler: { (action) in completionHandler(false) })) 118 | 119 | present(alertController, animated: true, completion: nil) 120 | } 121 | 122 | func webView(_ webView: WKWebView, runJavaScriptTextInputPanelWithPrompt prompt: String, defaultText: String?, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping (String?) -> Void) { 123 | 124 | let alertController = UIAlertController(title: nil, message: prompt, preferredStyle: .alert) 125 | 126 | alertController.addTextField { (textField) in textField.text = defaultText } 127 | 128 | alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: { (action) in 129 | if let text = alertController.textFields?.first?.text { 130 | completionHandler(text) 131 | } else { 132 | completionHandler(defaultText) 133 | } 134 | })) 135 | 136 | alertController.addAction(UIAlertAction(title: "Cancel", style: .default, handler: { (action) in completionHandler(nil) })) 137 | 138 | present(alertController, animated: true, completion: nil) 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /Share to Roam/Base.lproj/MainInterface.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 | -------------------------------------------------------------------------------- /Share to Roam/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDisplayName 6 | Roam Research 7 | NSExtension 8 | 9 | NSExtensionAttributes 10 | 11 | NSExtensionActivationRule 12 | 13 | NSExtensionActivationSupportsText 14 | 15 | NSExtensionActivationSupportsWebURLWithMaxCount 16 | 1 17 | 18 | 19 | NSExtensionPointIdentifier 20 | com.apple.share-services 21 | NSExtensionPrincipalClass 22 | CustomShareNavigationController 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /Share to Roam/Share to Roam.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.application-groups 6 | 7 | group.me.m1guelpf.RoamResearch 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Share to Roam/Share to RoamRelease.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.application-groups 6 | 7 | group.me.m1guelpf.RoamResearch 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Share to Roam/ShareViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ShareViewController.swift 3 | // Share to Roam 4 | // 5 | // Created by Miguel Piedrafita on 7/8/21. 6 | // 7 | 8 | import UIKit 9 | import WebKit 10 | 11 | class CustomShareViewController: UIViewController { 12 | let userDefaults: UserDefaults = UserDefaults.init(suiteName: "group.me.m1guelpf.RoamResearch")! 13 | 14 | private var urlString: String? { 15 | didSet { 16 | reloadWebview() 17 | } 18 | } 19 | 20 | private var textString: String? { 21 | didSet { 22 | reloadWebview() 23 | } 24 | } 25 | 26 | private var webViewUrl: String { 27 | let encodedText = textString?.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) ?? "" 28 | let encodedUrl = urlString?.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) ?? "" 29 | 30 | return "https://roamresearch.com/?\(encodedText == "" ? "a" : "text=\(encodedText)")&\(encodedUrl == "" ? "b" : "url=\(encodedUrl)")#quick-capture" 31 | } 32 | 33 | private var webView: WKWebView? 34 | 35 | override func viewDidLoad() { 36 | super.viewDidLoad() 37 | 38 | ensureConfigured() 39 | loadShareContent() 40 | 41 | self.view.backgroundColor = .systemGray6 42 | setupNavBar() 43 | setupViews() 44 | } 45 | 46 | private func ensureConfigured() { 47 | let subgraphSlug = userDefaults.value(forKey: "subgraphSlug") 48 | 49 | if (subgraphSlug ?? nil) == nil { 50 | let alertController = UIAlertController(title: nil, message: "Please select a graph from the Roam app first.", preferredStyle: .alert) 51 | alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: { [self] (action) in self.cancelAction() })) 52 | 53 | present(alertController, animated: true, completion: nil) 54 | } 55 | 56 | } 57 | 58 | private func loadShareContent() { 59 | let extensionItem = extensionContext?.inputItems[0] as! NSExtensionItem 60 | 61 | for attachment in extensionItem.attachments! { 62 | if attachment.hasItemConformingToTypeIdentifier("public.url") { 63 | attachment.loadItem(forTypeIdentifier: "public.url", options: nil, completionHandler: { (results, error) in 64 | let url = results as! URL? 65 | self.urlString = url!.absoluteString 66 | }) 67 | } 68 | if attachment.hasItemConformingToTypeIdentifier("public.plain-text") { 69 | attachment.loadItem(forTypeIdentifier: "public.plain-text", options: nil, completionHandler: { (results, error) in 70 | let text = results as! String 71 | self.textString = text 72 | }) 73 | } 74 | } 75 | 76 | 77 | } 78 | 79 | // 2: Set the title and the navigation items 80 | private func setupNavBar() { 81 | self.navigationItem.title = "Roam Research" 82 | 83 | let itemCancel = UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: #selector(cancelAction)) 84 | self.navigationItem.setLeftBarButton(itemCancel, animated: false) 85 | 86 | let itemDone = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(doneAction)) 87 | self.navigationItem.setRightBarButton(itemDone, animated: false) 88 | } 89 | 90 | private func setupViews() { 91 | self.webView = WKWebView(frame: view.frame) 92 | self.webView!.navigationDelegate = self 93 | self.webView!.autoresizingMask = [.flexibleWidth, .flexibleHeight] 94 | self.view.addSubview(self.webView!) 95 | 96 | let request = URLRequest(url: URL(string: self.webViewUrl)!) 97 | self.webView!.load(request) 98 | } 99 | 100 | private func reloadWebview() { 101 | self.webView?.load(URLRequest(url: URL(string: self.webViewUrl)!)) 102 | } 103 | 104 | // 3: Define the actions for the navigation items 105 | @objc private func cancelAction () { 106 | let error = NSError(domain: "me.m1guelpf.RoamResearch", code: 0, userInfo: [NSLocalizedDescriptionKey: "User cancelled request"]) 107 | extensionContext?.cancelRequest(withError: error) 108 | } 109 | 110 | @objc private func doneAction() { 111 | extensionContext?.completeRequest(returningItems: [], completionHandler: nil) 112 | } 113 | } 114 | 115 | extension CustomShareViewController: WKNavigationDelegate { 116 | // Close prompt if loading Roam fails 117 | func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) { 118 | let alertController = UIAlertController(title: nil, message: error.localizedDescription, preferredStyle: .alert) 119 | alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: { [self] (action) in self.cancelAction() })) 120 | 121 | present(alertController, animated: true, completion: nil) 122 | } 123 | } 124 | 125 | @objc(CustomShareNavigationController) 126 | class CustomShareNavigationController: UINavigationController { 127 | 128 | override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) { 129 | super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) 130 | 131 | // 2: set the ViewControllers 132 | self.setViewControllers([CustomShareViewController()], animated: false) 133 | } 134 | 135 | @available(*, unavailable) 136 | required init?(coder aDecoder: NSCoder) { 137 | super.init(coder: aDecoder) 138 | } 139 | } 140 | --------------------------------------------------------------------------------