login almost working, added settings list

This commit is contained in:
aj 2020-02-21 01:24:09 +00:00
parent 2132e4d855
commit 54a3806908
8 changed files with 151 additions and 30 deletions

View File

@ -28,6 +28,7 @@
E9E30C2A23FEAA3A00574EEF /* TagRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9E30C2923FEAA3A00574EEF /* TagRow.swift */; }; E9E30C2A23FEAA3A00574EEF /* TagRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9E30C2923FEAA3A00574EEF /* TagRow.swift */; };
E9E30C2D23FEAB0200574EEF /* TagView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9E30C2C23FEAB0200574EEF /* TagView.swift */; }; E9E30C2D23FEAB0200574EEF /* TagView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9E30C2C23FEAB0200574EEF /* TagView.swift */; };
E9E30C3123FEAF2B00574EEF /* TagObjList.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9E30C3023FEAF2B00574EEF /* TagObjList.swift */; }; E9E30C3123FEAF2B00574EEF /* TagObjList.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9E30C3023FEAF2B00574EEF /* TagObjList.swift */; };
E9E30C3323FF255C00574EEF /* SettingsList.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9E30C3223FF255C00574EEF /* SettingsList.swift */; };
E9EA690B23F9A5430012C3E8 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9EA690A23F9A5430012C3E8 /* AppDelegate.swift */; }; E9EA690B23F9A5430012C3E8 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9EA690A23F9A5430012C3E8 /* AppDelegate.swift */; };
E9EA690D23F9A5430012C3E8 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9EA690C23F9A5430012C3E8 /* SceneDelegate.swift */; }; E9EA690D23F9A5430012C3E8 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9EA690C23F9A5430012C3E8 /* SceneDelegate.swift */; };
E9EA690F23F9A5430012C3E8 /* RootView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9EA690E23F9A5430012C3E8 /* RootView.swift */; }; E9EA690F23F9A5430012C3E8 /* RootView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9EA690E23F9A5430012C3E8 /* RootView.swift */; };
@ -74,6 +75,7 @@
E9E30C2923FEAA3A00574EEF /* TagRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TagRow.swift; sourceTree = "<group>"; }; E9E30C2923FEAA3A00574EEF /* TagRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TagRow.swift; sourceTree = "<group>"; };
E9E30C2C23FEAB0200574EEF /* TagView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TagView.swift; sourceTree = "<group>"; }; E9E30C2C23FEAB0200574EEF /* TagView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TagView.swift; sourceTree = "<group>"; };
E9E30C3023FEAF2B00574EEF /* TagObjList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TagObjList.swift; sourceTree = "<group>"; }; E9E30C3023FEAF2B00574EEF /* TagObjList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TagObjList.swift; sourceTree = "<group>"; };
E9E30C3223FF255C00574EEF /* SettingsList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsList.swift; sourceTree = "<group>"; };
E9EA690723F9A5430012C3E8 /* Music Tools.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Music Tools.app"; sourceTree = BUILT_PRODUCTS_DIR; }; E9EA690723F9A5430012C3E8 /* Music Tools.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Music Tools.app"; sourceTree = BUILT_PRODUCTS_DIR; };
E9EA690A23F9A5430012C3E8 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; }; E9EA690A23F9A5430012C3E8 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
E9EA690C23F9A5430012C3E8 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; }; E9EA690C23F9A5430012C3E8 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; };
@ -151,6 +153,7 @@
E98254C023F9FFDD0056D9D3 /* Views */ = { E98254C023F9FFDD0056D9D3 /* Views */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
E9E30C3423FF256100574EEF /* Settings */,
E9E30C2F23FEACF700574EEF /* Tag */, E9E30C2F23FEACF700574EEF /* Tag */,
E9E30C2E23FEACDE00574EEF /* Playlist */, E9E30C2E23FEACDE00574EEF /* Playlist */,
E9EA690E23F9A5430012C3E8 /* RootView.swift */, E9EA690E23F9A5430012C3E8 /* RootView.swift */,
@ -191,6 +194,14 @@
path = Tag; path = Tag;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
E9E30C3423FF256100574EEF /* Settings */ = {
isa = PBXGroup;
children = (
E9E30C3223FF255C00574EEF /* SettingsList.swift */,
);
path = Settings;
sourceTree = "<group>";
};
E9EA68FE23F9A5430012C3E8 = { E9EA68FE23F9A5430012C3E8 = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
@ -399,6 +410,7 @@
E9E30C3123FEAF2B00574EEF /* TagObjList.swift in Sources */, E9E30C3123FEAF2B00574EEF /* TagObjList.swift in Sources */,
E98254CA23FA26600056D9D3 /* PlaylistRow.swift in Sources */, E98254CA23FA26600056D9D3 /* PlaylistRow.swift in Sources */,
E9EA690B23F9A5430012C3E8 /* AppDelegate.swift in Sources */, E9EA690B23F9A5430012C3E8 /* AppDelegate.swift in Sources */,
E9E30C3323FF255C00574EEF /* SettingsList.swift in Sources */,
E9EA690D23F9A5430012C3E8 /* SceneDelegate.swift in Sources */, E9EA690D23F9A5430012C3E8 /* SceneDelegate.swift in Sources */,
E98254DB23FB64740056D9D3 /* Network.swift in Sources */, E98254DB23FB64740056D9D3 /* Network.swift in Sources */,
E9E30C2A23FEAA3A00574EEF /* TagRow.swift in Sources */, E9E30C2A23FEAA3A00574EEF /* TagRow.swift in Sources */,

View File

@ -13,19 +13,17 @@ import KeychainAccess
@UIApplicationMain @UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate { class AppDelegate: UIResponder, UIApplicationDelegate {
var liveUser: LiveUser?
var loading = true
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch. // Override point for customization after application launch.
let keychain = Keychain(service: "xyz.sarsoo.music.login") let keychain = Keychain(service: "xyz.sarsoo.music.login")
keychain["username"] = "" // do {
keychain["password"] = "" // try keychain.remove("username")
// try keychain.remove("password")
liveUser = LiveUser(playlists: [], tags: []) // } catch let error {
// debugPrint("Could not clear keychain, \(error)")
// }
//
return true return true
} }

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="15705" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="aYE-zJ-V1n"> <document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="15705" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="Spt-Mn-jmg">
<device id="retina6_1" orientation="portrait" appearance="light"/> <device id="retina6_1" orientation="portrait" appearance="light"/>
<dependencies> <dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="15706"/> <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="15706"/>
@ -25,6 +25,9 @@
<rect key="frame" x="215.5" y="546" width="81" height="53"/> <rect key="frame" x="215.5" y="546" width="81" height="53"/>
<fontDescription key="fontDescription" style="UICTFontTextStyleTitle0"/> <fontDescription key="fontDescription" style="UICTFontTextStyleTitle0"/>
<state key="normal" title="Login"/> <state key="normal" title="Login"/>
<connections>
<segue destination="aYE-zJ-V1n" kind="show" id="Lhx-kz-pef"/>
</connections>
</button> </button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="6UM-RX-7fe"> <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="6UM-RX-7fe">
<rect key="frame" x="196" y="633" width="120" height="53"/> <rect key="frame" x="196" y="633" width="120" height="53"/>
@ -64,19 +67,29 @@
</objects> </objects>
<point key="canvasLocation" x="48" y="304"/> <point key="canvasLocation" x="48" y="304"/>
</scene> </scene>
<!--Hosting Controller-->
<scene sceneID="jWQ-vc-Ihe">
<objects>
<hostingController id="fqF-FS-fj3" sceneMemberID="viewController">
<navigationItem key="navigationItem" id="WZ3-YV-Zxu"/>
</hostingController>
<placeholder placeholderIdentifier="IBFirstResponder" id="7Vf-Lo-xr9" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="1728" y="-132"/>
</scene>
<!--Login Controller--> <!--Login Controller-->
<scene sceneID="Cbq-wX-wg3"> <scene sceneID="Cbq-wX-wg3">
<objects> <objects>
<viewController id="aYE-zJ-V1n" customClass="LoginController" customModule="Music_Tools" sceneMemberID="viewController"> <viewController id="aYE-zJ-V1n" customClass="LoginController" customModule="Music_Tools" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="cjE-Uz-adD"> <view key="view" contentMode="scaleToFill" id="cjE-Uz-adD">
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/> <rect key="frame" x="0.0" y="0.0" width="414" height="842"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews> <subviews>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" image="MusicToolsLogo" translatesAutoresizingMaskIntoConstraints="NO" id="Aa0-TI-VfP"> <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" image="MusicToolsLogo" translatesAutoresizingMaskIntoConstraints="NO" id="Aa0-TI-VfP">
<rect key="frame" x="0.0" y="94" width="414" height="433"/> <rect key="frame" x="0.0" y="50" width="414" height="423"/>
</imageView> </imageView>
<textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="bezel" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="Jsz-1T-t1A"> <textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="bezel" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="Jsz-1T-t1A">
<rect key="frame" x="20" y="589" width="374" height="34"/> <rect key="frame" x="20" y="535" width="374" height="34"/>
<constraints> <constraints>
<constraint firstAttribute="height" constant="34" id="ThQ-Jz-RB7"/> <constraint firstAttribute="height" constant="34" id="ThQ-Jz-RB7"/>
</constraints> </constraints>
@ -84,7 +97,7 @@
<textInputTraits key="textInputTraits" textContentType="username"/> <textInputTraits key="textInputTraits" textContentType="username"/>
</textField> </textField>
<textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="bezel" textAlignment="natural" minimumFontSize="17" clearButtonMode="whileEditing" translatesAutoresizingMaskIntoConstraints="NO" id="c5V-bv-fGr"> <textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="bezel" textAlignment="natural" minimumFontSize="17" clearButtonMode="whileEditing" translatesAutoresizingMaskIntoConstraints="NO" id="c5V-bv-fGr">
<rect key="frame" x="20" y="682" width="374" height="34"/> <rect key="frame" x="20" y="628" width="374" height="34"/>
<constraints> <constraints>
<constraint firstAttribute="height" constant="34" id="ynd-9a-coG"/> <constraint firstAttribute="height" constant="34" id="ynd-9a-coG"/>
</constraints> </constraints>
@ -92,7 +105,7 @@
<textInputTraits key="textInputTraits" returnKeyType="go" textContentType="password"/> <textInputTraits key="textInputTraits" returnKeyType="go" textContentType="password"/>
</textField> </textField>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="6YH-OC-12B"> <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="6YH-OC-12B">
<rect key="frame" x="185.5" y="766" width="43" height="53"/> <rect key="frame" x="185.5" y="712" width="43" height="53"/>
<constraints> <constraints>
<constraint firstAttribute="height" constant="53" id="udu-LZ-6uK"/> <constraint firstAttribute="height" constant="53" id="udu-LZ-6uK"/>
</constraints> </constraints>
@ -101,11 +114,12 @@
<color key="titleShadowColor" white="0.33333333333333331" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> <color key="titleShadowColor" white="0.33333333333333331" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</state> </state>
<connections> <connections>
<action selector="login:" destination="aYE-zJ-V1n" eventType="touchUpInside" id="G3y-eM-24U"/> <action selector="doLogin:" destination="aYE-zJ-V1n" eventType="touchUpInside" id="J5V-GY-yG6"/>
<segue destination="fqF-FS-fj3" kind="showDetail" identifier="loginToMain" destinationCreationSelector="returnUIView:" id="xcT-J7-nTv"/>
</connections> </connections>
</button> </button>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Username" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="CNh-mk-uV0"> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Username" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="CNh-mk-uV0">
<rect key="frame" x="167.5" y="560" width="79" height="21"/> <rect key="frame" x="167.5" y="506" width="79" height="21"/>
<constraints> <constraints>
<constraint firstAttribute="height" constant="21" id="oKd-GV-oVN"/> <constraint firstAttribute="height" constant="21" id="oKd-GV-oVN"/>
</constraints> </constraints>
@ -114,7 +128,7 @@
<nil key="highlightedColor"/> <nil key="highlightedColor"/>
</label> </label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Password" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="mvf-wa-Hkg"> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Password" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="mvf-wa-Hkg">
<rect key="frame" x="170" y="653" width="74" height="21"/> <rect key="frame" x="170" y="599" width="74" height="21"/>
<constraints> <constraints>
<constraint firstAttribute="height" constant="21" id="glG-PD-dHg"/> <constraint firstAttribute="height" constant="21" id="glG-PD-dHg"/>
</constraints> </constraints>
@ -144,8 +158,8 @@
</constraints> </constraints>
<viewLayoutGuide key="safeArea" id="JQv-rE-o2m"/> <viewLayoutGuide key="safeArea" id="JQv-rE-o2m"/>
</view> </view>
<navigationItem key="navigationItem" id="otB-Y9-KWi"/>
<connections> <connections>
<outlet property="goButton" destination="6YH-OC-12B" id="JFW-b1-k9S"/>
<outlet property="passwordField" destination="c5V-bv-fGr" id="9LJ-hb-7Jx"/> <outlet property="passwordField" destination="c5V-bv-fGr" id="9LJ-hb-7Jx"/>
<outlet property="usernameField" destination="Jsz-1T-t1A" id="QOC-fI-XsH"/> <outlet property="usernameField" destination="Jsz-1T-t1A" id="QOC-fI-XsH"/>
</connections> </connections>

View File

@ -8,6 +8,7 @@
import UIKit import UIKit
import SwiftUI import SwiftUI
import KeychainAccess
class SceneDelegate: UIResponder, UIWindowSceneDelegate { class SceneDelegate: UIResponder, UIWindowSceneDelegate {
@ -21,15 +22,29 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
// Create the SwiftUI view that provides the window contents. // Create the SwiftUI view that provides the window contents.
let contentView = RootView() let contentView = RootView()
var liveUser: LiveUser? let liveUser = LiveUser(playlists: [], tags: [])
if let appDelegate = UIApplication.shared.delegate as? AppDelegate {
liveUser = appDelegate.liveUser let keychain = Keychain(service: "xyz.sarsoo.music.login")
}
// debugPrint(keychain["username"] ?? "no username")
// debugPrint(keychain["password"] ?? "no password")
// Use a UIHostingController as window root view controller. // Use a UIHostingController as window root view controller.
if let windowScene = scene as? UIWindowScene { if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene) let window = UIWindow(windowScene: windowScene)
window.rootViewController = UIHostingController(rootView: contentView.environmentObject(liveUser ?? LiveUser(playlists: [], tags: [])))
var controller: UIViewController
if keychain["username"] != nil && keychain["password"] != nil {
controller = UIHostingController(rootView: contentView.environmentObject(liveUser))
} else {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
controller = storyboard.instantiateInitialViewController()!
}
window.rootViewController = controller
// window.rootViewController = UIHostingController(rootView: contentView.environmentObject(liveUser))
// window.rootViewController = LoginController()
self.window = window self.window = window
window.makeKeyAndVisible() window.makeKeyAndVisible()
} }

View File

@ -7,6 +7,8 @@
// //
import UIKit import UIKit
import SwiftUI
import KeychainAccess
class LoginController: UIViewController, UITextFieldDelegate { class LoginController: UIViewController, UITextFieldDelegate {
@ -24,11 +26,54 @@ class LoginController: UIViewController, UITextFieldDelegate {
} }
// MARK: Actions // MARK: Actions
@IBSegueAction func returnUIView(_ coder: NSCoder) -> UIViewController? {
@IBAction func login(_ sender: UIButton) { let liveUser = LiveUser(playlists: [], tags: [])
debugPrint(usernameField?.text) return UIHostingController(coder: coder, rootView: RootView().environmentObject(liveUser))
} }
var isLoggedIn: Bool? = nil {
didSet {
if self.isLoggedIn == true {
self.performSegue(withIdentifier: "loginToMain", sender: self)
} else if self.isLoggedIn == false {
debugPrint("false logged in")
self.isLoggedIn = nil
} else {
debugPrint("nil state")
}
}
}
@IBAction func doLogin(_ sender: Any) {
let keychain = Keychain(service: "xyz.sarsoo.music.login")
keychain["username"] = usernameField.text
keychain["password"] = passwordField.text
let api = UserApi.getUser
RequestBuilder.buildRequest(apiRequest: api).responseJSON{ response in
switch response.result {
case .success:
self.isLoggedIn = true
break
case .failure(let error):
debugPrint("error: \(error)")
self.isLoggedIn = false
do {
try keychain.remove("username")
try keychain.remove("password")
} catch let error {
debugPrint("Could not clear keychain, \(error)")
}
break
}
}
}
// block initial segue from button presson
override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool { return false }
// MARK: UITextFieldDelegate // MARK: UITextFieldDelegate
func textFieldShouldReturn(_ textField: UITextField) -> Bool { func textFieldShouldReturn(_ textField: UITextField) -> Bool {

View File

@ -39,6 +39,8 @@
</dict> </dict>
<key>UILaunchStoryboardName</key> <key>UILaunchStoryboardName</key>
<string>LaunchScreen</string> <string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UIRequiredDeviceCapabilities</key> <key>UIRequiredDeviceCapabilities</key>
<array> <array>
<string>armv7</string> <string>armv7</string>

View File

@ -112,9 +112,10 @@ struct RootView: View {
.tag(1) .tag(1)
// SETTINGS // SETTINGS
Text("Settings") NavigationView {
.font(.title) SettingsList()
.tabItem { .navigationBarTitle(Text("Settings").font(.title))
}.tabItem {
VStack { VStack {
Image(systemName: "slider.horizontal.3") Image(systemName: "slider.horizontal.3")
Text("Settings") Text("Settings")

View File

@ -0,0 +1,34 @@
//
// SettingsList.swift
// Music Tools
//
// Created by Andy Pack on 20/02/2020.
// Copyright © 2020 Sarsoo. All rights reserved.
//
import SwiftUI
import KeychainAccess
struct SettingsList: View {
var body: some View {
List{
Button(action: {
let keychain = Keychain(service: "xyz.sarsoo.music.login")
do {
try keychain.remove("username")
try keychain.remove("password")
} catch let error {
debugPrint("Could not clear keychain, \(error)")
}
}) {
Text("Log out")
}
}
}
}
struct SettingsList_Previews: PreviewProvider {
static var previews: some View {
SettingsList()
}
}