Browse Source

Development

master
Dwayne Harris 6 years ago
parent
commit
7b30710582
  1. 16
      Package.resolved
  2. 28
      Package.swift
  3. 3
      Sources/elpha-ios/elpha_ios.swift
  4. 7
      Tests/LinuxMain.swift
  5. 9
      Tests/elpha-iosTests/XCTestManifests.swift
  6. 16
      Tests/elpha-iosTests/elpha_iosTests.swift
  7. 10
      elpha-ios.xcodeproj/project.pbxproj
  8. 98
      elpha-ios/APIRequest.swift
  9. 25
      elpha-ios/AppDelegate.swift
  10. BIN
      elpha-ios/Assets.xcassets/Globe.imageset/globe-white.pdf
  11. 70
      elpha-ios/AuthenticateViewController.swift
  12. 28
      elpha-ios/Base.lproj/LaunchScreen.storyboard
  13. 9
      elpha-ios/Base.lproj/Main.storyboard
  14. 2
      elpha-ios/Configuration.swift
  15. 23
      elpha-ios/Elpha.xcdatamodeld/Elpha.xcdatamodel/contents
  16. 11
      elpha-ios/Info.plist
  17. 13
      elpha-ios/InstanceViewController.swift

16
Package.resolved

@ -1,16 +0,0 @@
{
"object": {
"pins": [
{
"package": "Kingfisher",
"repositoryURL": "https://github.com/onevcat/Kingfisher.git",
"state": {
"branch": null,
"revision": "b6d83f8520a81996738b40d3cbfdad939ceab2b3",
"version": "4.9.0"
}
}
]
},
"version": 1
}

28
Package.swift

@ -1,28 +0,0 @@
// swift-tools-version:4.0
// The swift-tools-version declares the minimum version of Swift required to build this package.
import PackageDescription
let package = Package(
name: "elpha-ios",
products: [
// Products define the executables and libraries produced by a package, and make them visible to other packages.
.library(
name: "elpha-ios",
targets: ["elpha-ios"]),
],
dependencies: [
// Dependencies declare other packages that this package depends on.
// .package(url: /* package url */, from: "1.0.0"),
],
targets: [
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
// Targets can depend on other targets in this package, and on products in packages which this package depends on.
.target(
name: "elpha-ios",
dependencies: []),
.testTarget(
name: "elpha-iosTests",
dependencies: ["elpha-ios"]),
]
)

3
Sources/elpha-ios/elpha_ios.swift

@ -1,3 +0,0 @@
struct elpha_ios {
var text = "Hello, World!"
}

7
Tests/LinuxMain.swift

@ -1,7 +0,0 @@
import XCTest
import elpha_iosTests
var tests = [XCTestCaseEntry]()
tests += elpha_iosTests.allTests()
XCTMain(tests)

9
Tests/elpha-iosTests/XCTestManifests.swift

@ -1,9 +0,0 @@
import XCTest
#if !os(macOS)
public func allTests() -> [XCTestCaseEntry] {
return [
testCase(elpha_iosTests.allTests),
]
}
#endif

16
Tests/elpha-iosTests/elpha_iosTests.swift

@ -1,16 +0,0 @@
import XCTest
@testable import elpha_ios
final class elpha_iosTests: XCTestCase {
func testExample() {
// This is an example of a functional test case.
// Use XCTAssert and related functions to verify your tests produce the correct
// results.
XCTAssertEqual(elpha_ios().text, "Hello, World!")
}
static var allTests = [
("testExample", testExample),
]
}

10
elpha-ios.xcodeproj/project.pbxproj

@ -10,6 +10,7 @@
157405A82150588A00EEAAEB /* InstanceViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 157405A72150588A00EEAAEB /* InstanceViewController.swift */; };
157405B12151A5DA00EEAAEB /* README.md in Resources */ = {isa = PBXBuildFile; fileRef = 157405AF2151A5DA00EEAAEB /* README.md */; };
157405B42151A93E00EEAAEB /* InstancesDataManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 157405B32151A93E00EEAAEB /* InstancesDataManager.swift */; };
157405B621534B2C00EEAAEB /* APIRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 157405B521534B2C00EEAAEB /* APIRequest.swift */; };
15830D93214F6F6F0037C342 /* ImageCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 15830D92214F6F6F0037C342 /* ImageCache.swift */; };
159048AF214F5015004F4014 /* InstancesTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 159048AE214F5015004F4014 /* InstancesTableViewCell.swift */; };
15960E5B213145E100C38CE9 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 15960E5A213145E100C38CE9 /* AppDelegate.swift */; };
@ -32,8 +33,8 @@
/* Begin PBXFileReference section */
157405A72150588A00EEAAEB /* InstanceViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstanceViewController.swift; sourceTree = "<group>"; };
157405AF2151A5DA00EEAAEB /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
157405B02151A5DA00EEAAEB /* Package.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Package.swift; sourceTree = "<group>"; };
157405B32151A93E00EEAAEB /* InstancesDataManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstancesDataManager.swift; sourceTree = "<group>"; };
157405B521534B2C00EEAAEB /* APIRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = APIRequest.swift; sourceTree = "<group>"; };
15830D92214F6F6F0037C342 /* ImageCache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageCache.swift; sourceTree = "<group>"; };
159048AE214F5015004F4014 /* InstancesTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstancesTableViewCell.swift; sourceTree = "<group>"; };
15960E57213145E100C38CE9 /* elpha-ios.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "elpha-ios.app"; sourceTree = BUILT_PRODUCTS_DIR; };
@ -70,7 +71,6 @@
isa = PBXGroup;
children = (
157405AF2151A5DA00EEAAEB /* README.md */,
157405B02151A5DA00EEAAEB /* Package.swift */,
15960E59213145E100C38CE9 /* elpha-ios */,
15960E58213145E100C38CE9 /* Products */,
);
@ -87,9 +87,8 @@
15960E59213145E100C38CE9 /* elpha-ios */ = {
isa = PBXGroup;
children = (
15960E7121322B9F00C38CE9 /* Keychain Helper */,
15960E782132383600C38CE9 /* View Controllers */,
15960E68213145E200C38CE9 /* Info.plist */,
157405B521534B2C00EEAAEB /* APIRequest.swift */,
15960E5A213145E100C38CE9 /* AppDelegate.swift */,
15960E7B213272CD00C38CE9 /* AuthenticationManager.swift */,
15960E7621322C6F00C38CE9 /* Configuration.swift */,
@ -97,8 +96,10 @@
157405B32151A93E00EEAAEB /* InstancesDataManager.swift */,
15960E63213145E200C38CE9 /* Assets.xcassets */,
15960E6E21321FA500C38CE9 /* Elpha.xcdatamodeld */,
15960E7121322B9F00C38CE9 /* Keychain Helper */,
15960E65213145E200C38CE9 /* LaunchScreen.storyboard */,
15960E60213145E100C38CE9 /* Main.storyboard */,
15960E782132383600C38CE9 /* View Controllers */,
);
path = "elpha-ios";
sourceTree = "<group>";
@ -214,6 +215,7 @@
15960E7721322C6F00C38CE9 /* Configuration.swift in Sources */,
15960E7521322BF800C38CE9 /* KeychainWrapper.swift in Sources */,
157405A82150588A00EEAAEB /* InstanceViewController.swift in Sources */,
157405B621534B2C00EEAAEB /* APIRequest.swift in Sources */,
15960E7321322BC700C38CE9 /* KeychainItemAccessibility.swift in Sources */,
15960E822136668500C38CE9 /* TimelinesNavigationController.swift in Sources */,
);

98
elpha-ios/APIRequest.swift

@ -0,0 +1,98 @@
//
// APIRequest.swift
// elpha-ios
//
// Created by Dwayne Harris on 9/19/18.
// Copyright © 2018 Elpha. All rights reserved.
//
import Foundation
extension URLRequest {
private func percentEscapeString(_ string: String) -> String {
var characterSet = CharacterSet.alphanumerics
characterSet.insert(charactersIn: "-._* ")
return string
.addingPercentEncoding(withAllowedCharacters: characterSet)!
.replacingOccurrences(of: " ", with: "+")
}
mutating func encodeParameters(parameters: [String: String]) {
httpMethod = "POST"
let parameterArray = parameters.map { (arg) -> String in
let (key, value) = arg
return "\(key)=\(self.percentEscapeString(value))"
}
httpBody = parameterArray.joined(separator: "&").data(using: .utf8)
}
}
class APIRequest {
static func get(url: URL, completion: @escaping ([String: Any]?, Error?) -> Void) {
let request = URLRequest(url: url)
URLSession.shared.dataTask(with: request) { data, response, error in
guard error == nil else {
completion(nil, error)
return
}
guard let data = data else {
completion(nil, NSError())
return
}
do {
completion(try JSONSerialization.jsonObject(with: data) as? [String: Any], nil)
} catch {
completion(nil, error)
}
}
}
static func post(url: URL, data: [String: String], completion: @escaping ([String: Any]?, Error?) -> Void) {
var request = URLRequest(url: url)
request.setValue("application/json", forHTTPHeaderField: "Accept")
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
request.encodeParameters(parameters: data)
URLSession.shared.dataTask(with: request) { data, response, error in
guard error == nil else {
completion(nil, error)
return
}
guard let data = data else {
completion(nil, NSError())
return
}
completion(try? JSONSerialization.jsonObject(with: data) as! [String: Any], nil)
}
}
static func handleOAuthResponse(url: URL) throws {
}
static func registerApp(instance: URL, completion: @escaping ([String: Any]?, Error?) -> Void) {
let data = [
"client_name": Config.clientName,
"redirect_uris": "elpha:authenticate",
"scopes": "read write follow",
"website": Config.clientWebsite
]
APIRequest.post(url: instance.appendingPathComponent("api/v1/apps"), data: data) { data, error in
guard error == nil else {
completion(nil, error)
return
}
completion(data, nil)
}
}
}

25
elpha-ios/AppDelegate.swift

@ -19,6 +19,31 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
// Override point for customization after application launch.
return true
}
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
guard let components = NSURLComponents(url: url, resolvingAgainstBaseURL: true),
let path = components.path else {
return false
}
guard url.host == "oauth-callback" else {
return false
}
switch path {
case "authenticate":
do {
try APIRequest.handleOAuthResponse(url: url)
return true
} catch {
print("\(error)")
return false
}
default:
print("Unknown path: \(path)")
return false
}
}
func applicationWillResignActive(_ application: UIApplication) {
// 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.

BIN
elpha-ios/Assets.xcassets/Globe.imageset/globe-white.pdf

70
elpha-ios/AuthenticateViewController.swift

@ -6,6 +6,7 @@
// Copyright © 2018 Elpha. All rights reserved.
//
import CoreData
import UIKit
class AuthenticateViewController: UIViewController {
@ -22,4 +23,73 @@ class AuthenticateViewController: UIViewController {
override open var shouldAutorotate: Bool {
return false
}
func saveApp(id: String, clientID: String, clientSecret: String, url: String) {
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
let app = AppMO(context: context)
app.id = id
app.clientID = clientID
app.url = url
do {
try context.save()
} catch {
fatalError("Couldn't save app")
}
}
func startOAuth() {
}
@IBAction func signIn(_ sender: Any) {
guard var url = instanceTextField.text, !url.isEmpty else {
return
}
if url.contains("@") {
if let urlPart = url.split(separator: "@").last {
url = String(urlPart)
} else {
return
}
}
if url.starts(with: "http") {
let regex = try! NSRegularExpression(pattern: "https?://")
url = regex.stringByReplacingMatches(in: url, options: [], range: NSMakeRange(0, url.count), withTemplate: "")
}
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
let request = NSFetchRequest<AppMO>(entityName: "App")
request.predicate = NSPredicate(format: "url == %@", url)
do {
let response = try context.fetch(request)
switch response.count {
case 0:
APIRequest.registerApp(instance: URL(string: url)!) { data, error in
guard error == nil else {
print("Couldn't register app")
return
}
if let data = data,
let id = data["id"] as? String,
let clientID = data["client_id"] as? String,
let clientSecret = data["client_secret"] as? String {
self.saveApp(id: id, clientID: clientID, clientSecret: clientSecret, url: url)
}
}
case 1:
print("")
return
default:
fatalError("Duplicate App entities")
}
} catch {
print("\(error)")
}
}
}

28
elpha-ios/Base.lproj/LaunchScreen.storyboard

@ -1,11 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14113" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14313.18" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14088"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14283.14"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
@ -18,21 +17,28 @@
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="Elpha" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="pds-N4-1zg">
<rect key="frame" x="139" y="309" width="96" height="48"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="40"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="Logo" translatesAutoresizingMaskIntoConstraints="NO" id="yHN-UZ-oQW">
<rect key="frame" x="137.5" y="233.5" width="100" height="100"/>
<constraints>
<constraint firstAttribute="height" constant="100" id="ffu-M7-gK2"/>
<constraint firstAttribute="width" constant="100" id="g0I-zi-ioB"/>
</constraints>
</imageView>
</subviews>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="yHN-UZ-oQW" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="centerY" constant="-50" id="R1t-lu-lFN"/>
<constraint firstItem="yHN-UZ-oQW" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="rXL-Vx-sGx"/>
</constraints>
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="53" y="375"/>
<point key="canvasLocation" x="52" y="374.66266866566718"/>
</scene>
</scenes>
<resources>
<image name="Logo" width="400" height="400"/>
</resources>
</document>

9
elpha-ios/Base.lproj/Main.storyboard

@ -58,6 +58,9 @@
<state key="normal" title="Sign In">
<color key="titleColor" red="0.99999600649999998" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</state>
<connections>
<action selector="signIn:" destination="Bed-pj-wE9" eventType="touchUpInside" id="zZW-2U-J5d"/>
</connections>
</button>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="TUU-fE-p3J">
<rect key="frame" x="0.0" y="806" width="414" height="90"/>
@ -297,9 +300,9 @@
</constraints>
<color key="tintColor" red="0.99999600649999998" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<inset key="imageEdgeInsets" minX="6" minY="6" maxX="6" maxY="6"/>
<state key="normal" title="Website" image="Globe"/>
<state key="normal" image="Globe"/>
<connections>
<action selector="webViewButtonPressed:" destination="mhy-lU-rss" eventType="touchUpInside" id="VYF-om-q5R"/>
<action selector="goToWebsite:" destination="mhy-lU-rss" eventType="touchUpInside" id="i0F-AS-ndD"/>
</connections>
</button>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="4Fj-SG-ZQ4">
@ -590,7 +593,7 @@
</scene>
</scenes>
<resources>
<image name="Globe" width="496" height="496"/>
<image name="Globe" width="25" height="25"/>
<image name="Instance Placeholder" width="60" height="60"/>
<image name="Logo" width="400" height="400"/>
<image name="Timelines" width="25" height="25"/>

2
elpha-ios/Configuration.swift

@ -10,6 +10,8 @@ import Foundation
struct Config {
static let clientName = "xyz.elpha.elpha-ios"
static let clientDisplayName = "Elpha"
static let clientWebsite = "https://elpha.xyz"
static let instancesServiceUrl = "https://instances.social"
static let instancesServiceEndpoint = "/api/1.0/instances/list"

23
elpha-ios/Elpha.xcdatamodeld/Elpha.xcdatamodel/contents

@ -3,16 +3,16 @@
<entity name="Account" representedClassName="AccountMO" syncable="YES" codeGenerationType="class">
<attribute name="acct" attributeType="String" syncable="YES"/>
<attribute name="avatarData" optional="YES" attributeType="Binary" syncable="YES"/>
<attribute name="avatarStaticUrl" optional="YES" attributeType="URI" syncable="YES"/>
<attribute name="avatarUrl" optional="YES" attributeType="URI" syncable="YES"/>
<attribute name="avatarStaticURL" optional="YES" attributeType="URI" syncable="YES"/>
<attribute name="avatarURL" optional="YES" attributeType="URI" syncable="YES"/>
<attribute name="bot" optional="YES" attributeType="Boolean" usesScalarValueType="YES" syncable="YES"/>
<attribute name="createdAt" attributeType="Date" usesScalarValueType="NO" syncable="YES"/>
<attribute name="displayName" attributeType="String" syncable="YES"/>
<attribute name="followersCount" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES" syncable="YES"/>
<attribute name="followingCount" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES" syncable="YES"/>
<attribute name="headerData" optional="YES" attributeType="Binary" syncable="YES"/>
<attribute name="headerStaticUrl" optional="YES" attributeType="URI" syncable="YES"/>
<attribute name="headerUrl" optional="YES" attributeType="URI" syncable="YES"/>
<attribute name="headerStaticURL" optional="YES" attributeType="URI" syncable="YES"/>
<attribute name="headerURL" optional="YES" attributeType="URI" syncable="YES"/>
<attribute name="id" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES" syncable="YES"/>
<attribute name="locked" attributeType="Boolean" usesScalarValueType="YES" syncable="YES"/>
<attribute name="moved" optional="YES" attributeType="String" syncable="YES"/>
@ -23,8 +23,9 @@
<relationship name="sessions" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Session" inverseName="account" inverseEntity="Session" syncable="YES"/>
</entity>
<entity name="App" representedClassName="AppMO" syncable="YES" codeGenerationType="class">
<attribute name="clientId" attributeType="String" syncable="YES"/>
<attribute name="id" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES" syncable="YES"/>
<attribute name="clientID" attributeType="String" syncable="YES"/>
<attribute name="id" attributeType="String" syncable="YES"/>
<attribute name="url" attributeType="String" syncable="YES"/>
<relationship name="sessions" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Session" inverseName="app" inverseEntity="Session" syncable="YES"/>
</entity>
<entity name="ISCategory" representedClassName="ISCategoryMO" syncable="YES" codeGenerationType="class">
@ -72,11 +73,11 @@
<relationship name="app" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="App" inverseName="sessions" inverseEntity="App" syncable="YES"/>
</entity>
<elements>
<element name="Account" positionX="-63" positionY="-18" width="128" height="345"/>
<element name="App" positionX="-54" positionY="135" width="128" height="90"/>
<element name="ISCategory" positionX="-27" positionY="144" width="128" height="75"/>
<element name="Account" positionX="-669.49609375" positionY="52.046875" width="128" height="345"/>
<element name="App" positionX="-244.4140625" positionY="307.203125" width="128" height="105"/>
<element name="ISCategory" positionX="196.8984375" positionY="498.03515625" width="128" height="75"/>
<element name="ISInstance" positionX="-18" positionY="153" width="128" height="435"/>
<element name="ISLanguage" positionX="-36" positionY="135" width="128" height="75"/>
<element name="Session" positionX="-36" positionY="144" width="128" height="135"/>
<element name="ISLanguage" positionX="-286.21875" positionY="512.6171875" width="128" height="75"/>
<element name="Session" positionX="-445.046875" positionY="277.31640625" width="128" height="135"/>
</elements>
</model>

11
elpha-ios/Info.plist

@ -46,6 +46,17 @@
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLName</key>
<string>xyz.elpha.elpha-ios</string>
<key>CFBundleURLSchemes</key>
<array>
<string>elpha</string>
</array>
</dict>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>

13
elpha-ios/InstanceViewController.swift

@ -21,7 +21,15 @@ class InstanceViewController: UIViewController, SFSafariViewControllerDelegate {
var instance: ISInstanceMO? = nil
@IBAction func webViewButtonPressed(_ sender: Any) {
override var previewActionItems: [UIPreviewActionItem] {
let action = UIPreviewAction(title: "Go to website", style: .default) { action, viewController in
self.presentSafariViewController()
}
return [action]
}
@IBAction func goToWebsite(_ sender: Any) {
presentSafariViewController()
}
@ -40,9 +48,12 @@ class InstanceViewController: UIViewController, SFSafariViewControllerDelegate {
super.viewDidLoad()
webViewButton.layer.cornerRadius = 15
if let instance = instance, let name = instance.name {
navigationItem.title = name
}
navigationItem.rightBarButtonItem = UIBarButtonItem(image: UIImage(named: "Globe"), style: .plain, target: self, action: #selector(presentSafariViewController))
}
override func viewWillAppear(_ animated: Bool) {

Loading…
Cancel
Save