add swiftUI code
@@ -0,0 +1,23 @@
|
||||
import Foundation
|
||||
import Library
|
||||
import SwiftUI
|
||||
|
||||
|
||||
@main
|
||||
struct Application: App {
|
||||
@UIApplicationDelegateAdaptor private var appDelegate: ApplicationDelegate
|
||||
@StateObject private var environments = ExtensionEnvironments()
|
||||
|
||||
@State private var isLoggedIn = UserManager.shared.isUserLoggedIn()
|
||||
|
||||
var body: some Scene {
|
||||
WindowGroup {
|
||||
if isLoggedIn {
|
||||
//MainView().environmentObject(environments)
|
||||
HomeView(isLoggedIn: $isLoggedIn).environmentObject(environments)
|
||||
}else{
|
||||
LoginContentView(isLoggedIn: $isLoggedIn)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
import ApplicationLibrary
|
||||
import Foundation
|
||||
import Libbox
|
||||
import Library
|
||||
import Network
|
||||
import UIKit
|
||||
|
||||
class ApplicationDelegate: NSObject, UIApplicationDelegate {
|
||||
private var profileServer: ProfileServer?
|
||||
|
||||
func application(_: UIApplication, didFinishLaunchingWithOptions _: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool {
|
||||
|
||||
LibboxSetup(FilePath.sharedDirectory.relativePath, FilePath.workingDirectory.relativePath, FilePath.cacheDirectory.relativePath, false)
|
||||
setup()
|
||||
return true
|
||||
}
|
||||
|
||||
private func setup() {
|
||||
do {
|
||||
try UIProfileUpdateTask.configure()
|
||||
NSLog("setup background task success")
|
||||
} catch {
|
||||
NSLog("setup background task error: \(error.localizedDescription)")
|
||||
}
|
||||
Task {
|
||||
if UIDevice.current.userInterfaceIdiom == .phone {
|
||||
await requestNetworkPermission()
|
||||
}
|
||||
await setupBackground()
|
||||
}
|
||||
}
|
||||
|
||||
private nonisolated func setupBackground() async {
|
||||
if #available(iOS 16.0, *) {
|
||||
do {
|
||||
let profileServer = try ProfileServer()
|
||||
profileServer.start()
|
||||
await MainActor.run {
|
||||
self.profileServer = profileServer
|
||||
}
|
||||
NSLog("started profile server")
|
||||
} catch {
|
||||
NSLog("setup profile server error: \(error.localizedDescription)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private nonisolated func requestNetworkPermission() async {
|
||||
if await SharedPreferences.networkPermissionRequested.get() {
|
||||
return
|
||||
}
|
||||
if !DeviceCensorship.isChinaDevice() {
|
||||
await SharedPreferences.networkPermissionRequested.set(true)
|
||||
return
|
||||
}
|
||||
URLSession.shared.dataTask(with: URL(string: "http://captive.apple.com")!) { _, response, _ in
|
||||
if let response = response as? HTTPURLResponse {
|
||||
if response.statusCode == 200 {
|
||||
Task {
|
||||
await SharedPreferences.networkPermissionRequested.set(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
}.resume()
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 190 KiB |
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "10-35-03.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 193 KiB |
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "10-35-15.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 299 KiB |
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "10-35-24.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 190 KiB |
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "11-53-53.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 121 KiB |
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "12-11-56.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 134 KiB |
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "12-14-11.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"colors": [
|
||||
{
|
||||
"idiom": "universal"
|
||||
}
|
||||
],
|
||||
"info": {
|
||||
"author": "xcode",
|
||||
"version": 1
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 4.3 KiB |
|
After Width: | Height: | Size: 196 KiB |
|
After Width: | Height: | Size: 5.2 KiB |
|
After Width: | Height: | Size: 5.7 KiB |
|
After Width: | Height: | Size: 7.4 KiB |
|
After Width: | Height: | Size: 8.0 KiB |
|
After Width: | Height: | Size: 9.2 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 628 B |
|
After Width: | Height: | Size: 949 B |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 3.2 KiB |
|
After Width: | Height: | Size: 3.6 KiB |
@@ -0,0 +1,158 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "40.png",
|
||||
"idiom" : "iphone",
|
||||
"scale" : "2x",
|
||||
"size" : "20x20"
|
||||
},
|
||||
{
|
||||
"filename" : "60.png",
|
||||
"idiom" : "iphone",
|
||||
"scale" : "3x",
|
||||
"size" : "20x20"
|
||||
},
|
||||
{
|
||||
"filename" : "29.png",
|
||||
"idiom" : "iphone",
|
||||
"scale" : "1x",
|
||||
"size" : "29x29"
|
||||
},
|
||||
{
|
||||
"filename" : "58.png",
|
||||
"idiom" : "iphone",
|
||||
"scale" : "2x",
|
||||
"size" : "29x29"
|
||||
},
|
||||
{
|
||||
"filename" : "87.png",
|
||||
"idiom" : "iphone",
|
||||
"scale" : "3x",
|
||||
"size" : "29x29"
|
||||
},
|
||||
{
|
||||
"filename" : "80.png",
|
||||
"idiom" : "iphone",
|
||||
"scale" : "2x",
|
||||
"size" : "40x40"
|
||||
},
|
||||
{
|
||||
"filename" : "120.png",
|
||||
"idiom" : "iphone",
|
||||
"scale" : "3x",
|
||||
"size" : "40x40"
|
||||
},
|
||||
{
|
||||
"filename" : "57.png",
|
||||
"idiom" : "iphone",
|
||||
"scale" : "1x",
|
||||
"size" : "57x57"
|
||||
},
|
||||
{
|
||||
"filename" : "114.png",
|
||||
"idiom" : "iphone",
|
||||
"scale" : "2x",
|
||||
"size" : "57x57"
|
||||
},
|
||||
{
|
||||
"filename" : "120.png",
|
||||
"idiom" : "iphone",
|
||||
"scale" : "2x",
|
||||
"size" : "60x60"
|
||||
},
|
||||
{
|
||||
"filename" : "180.png",
|
||||
"idiom" : "iphone",
|
||||
"scale" : "3x",
|
||||
"size" : "60x60"
|
||||
},
|
||||
{
|
||||
"filename" : "20.png",
|
||||
"idiom" : "ipad",
|
||||
"scale" : "1x",
|
||||
"size" : "20x20"
|
||||
},
|
||||
{
|
||||
"filename" : "40.png",
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x",
|
||||
"size" : "20x20"
|
||||
},
|
||||
{
|
||||
"filename" : "29.png",
|
||||
"idiom" : "ipad",
|
||||
"scale" : "1x",
|
||||
"size" : "29x29"
|
||||
},
|
||||
{
|
||||
"filename" : "58.png",
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x",
|
||||
"size" : "29x29"
|
||||
},
|
||||
{
|
||||
"filename" : "40.png",
|
||||
"idiom" : "ipad",
|
||||
"scale" : "1x",
|
||||
"size" : "40x40"
|
||||
},
|
||||
{
|
||||
"filename" : "80.png",
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x",
|
||||
"size" : "40x40"
|
||||
},
|
||||
{
|
||||
"filename" : "50.png",
|
||||
"idiom" : "ipad",
|
||||
"scale" : "1x",
|
||||
"size" : "50x50"
|
||||
},
|
||||
{
|
||||
"filename" : "100.png",
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x",
|
||||
"size" : "50x50"
|
||||
},
|
||||
{
|
||||
"filename" : "72.png",
|
||||
"idiom" : "ipad",
|
||||
"scale" : "1x",
|
||||
"size" : "72x72"
|
||||
},
|
||||
{
|
||||
"filename" : "144.png",
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x",
|
||||
"size" : "72x72"
|
||||
},
|
||||
{
|
||||
"filename" : "76.png",
|
||||
"idiom" : "ipad",
|
||||
"scale" : "1x",
|
||||
"size" : "76x76"
|
||||
},
|
||||
{
|
||||
"filename" : "152.png",
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x",
|
||||
"size" : "76x76"
|
||||
},
|
||||
{
|
||||
"filename" : "167.png",
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x",
|
||||
"size" : "83.5x83.5"
|
||||
},
|
||||
{
|
||||
"filename" : "1024.png",
|
||||
"idiom" : "ios-marketing",
|
||||
"scale" : "1x",
|
||||
"size" : "1024x1024"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0.322",
|
||||
"green" : "0.122",
|
||||
"red" : "0.192"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "display-p3",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0.314",
|
||||
"green" : "0.043",
|
||||
"red" : "0.106"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "display-p3",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0.271",
|
||||
"green" : "0.125",
|
||||
"red" : "0.161"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0.322",
|
||||
"green" : "0.122",
|
||||
"red" : "0.192"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
},
|
||||
{
|
||||
"appearances" : [
|
||||
{
|
||||
"appearance" : "luminosity",
|
||||
"value" : "dark"
|
||||
}
|
||||
],
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0.322",
|
||||
"green" : "0.122",
|
||||
"red" : "0.192"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0.322",
|
||||
"green" : "0.122",
|
||||
"red" : "0.192"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
},
|
||||
{
|
||||
"appearances" : [
|
||||
{
|
||||
"appearance" : "luminosity",
|
||||
"value" : "dark"
|
||||
}
|
||||
],
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0.322",
|
||||
"green" : "0.122",
|
||||
"red" : "0.192"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "fr.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 2.0 KiB |
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "germany.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 1.8 KiB |
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "in.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 2.8 KiB |
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "si.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 3.3 KiB |
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "uk.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 4.0 KiB |
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "us.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 5.5 KiB |
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0.322",
|
||||
"green" : "0.122",
|
||||
"red" : "0.192"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
},
|
||||
{
|
||||
"appearances" : [
|
||||
{
|
||||
"appearance" : "luminosity",
|
||||
"value" : "dark"
|
||||
}
|
||||
],
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0.322",
|
||||
"green" : "0.122",
|
||||
"red" : "0.192"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0.976",
|
||||
"green" : "0.443",
|
||||
"red" : "0.816"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
},
|
||||
{
|
||||
"appearances" : [
|
||||
{
|
||||
"appearance" : "luminosity",
|
||||
"value" : "dark"
|
||||
}
|
||||
],
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0.976",
|
||||
"green" : "0.443",
|
||||
"red" : "0.816"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "display-p3",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0.725",
|
||||
"green" : "0.506",
|
||||
"red" : "0.553"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "display-p3",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0.957",
|
||||
"green" : "0.831",
|
||||
"red" : "0.400"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "display-p3",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0.922",
|
||||
"green" : "0.427",
|
||||
"red" : "0.506"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "playstore.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 62 KiB |
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "playstore.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 62 KiB |
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "checkout.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 30 KiB |
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "globe.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 1.0 MiB |
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0.399",
|
||||
"green" : "0.349",
|
||||
"red" : "0.353"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
},
|
||||
{
|
||||
"appearances" : [
|
||||
{
|
||||
"appearance" : "luminosity",
|
||||
"value" : "dark"
|
||||
}
|
||||
],
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0.323",
|
||||
"green" : "0.331",
|
||||
"red" : "0.350"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0.339",
|
||||
"green" : "0.226",
|
||||
"red" : "0.255"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
},
|
||||
{
|
||||
"appearances" : [
|
||||
{
|
||||
"appearance" : "luminosity",
|
||||
"value" : "dark"
|
||||
}
|
||||
],
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0.362",
|
||||
"green" : "0.195",
|
||||
"red" : "0.339"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "listclipboard.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 20 KiB |
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "cartoon-1298905_1280.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 491 KiB |
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "message.badge.circle.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 2.1 KiB |
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "img4.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 318 KiB |
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "playstore.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 62 KiB |
@@ -0,0 +1,59 @@
|
||||
import ApplicationLibrary
|
||||
import Library
|
||||
import SwiftUI
|
||||
|
||||
struct ContentView: View {
|
||||
@Environment(\.selection) private var selection
|
||||
@Environment(\.extensionProfile) private var extensionProfile
|
||||
|
||||
var body: some View {
|
||||
viewBuilder {
|
||||
if let profile = extensionProfile.wrappedValue {
|
||||
ContentView0().environmentObject(profile)
|
||||
} else {
|
||||
ContentView1()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct ContentView0: View {
|
||||
@Environment(\.selection) private var selection
|
||||
@EnvironmentObject private var extensionProfile: ExtensionProfile
|
||||
|
||||
var body: some View {
|
||||
TabView(selection: selection) {
|
||||
ForEach(NavigationPage.allCases.filter { it in
|
||||
it.visible(extensionProfile)
|
||||
}, id: \.self) { page in
|
||||
NavigationStackCompat {
|
||||
page.contentView
|
||||
}
|
||||
.tag(page)
|
||||
.tabItem { page.label }
|
||||
}
|
||||
}.onChangeCompat(of: extensionProfile.status) {
|
||||
if !selection.wrappedValue.visible(extensionProfile) {
|
||||
selection.wrappedValue = NavigationPage.dashboard
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct ContentView1: View {
|
||||
@Environment(\.selection) private var selection
|
||||
|
||||
var body: some View {
|
||||
TabView(selection: selection) {
|
||||
ForEach(NavigationPage.allCases.filter { it in
|
||||
it.visible(nil)
|
||||
}, id: \.self) { page in
|
||||
NavigationStackCompat {
|
||||
page.contentView
|
||||
}
|
||||
.tag(page)
|
||||
.tabItem { page.label }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
{"v":"5.12.2","fr":60,"ip":0,"op":72,"w":500,"h":500,"nm":"Lock","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Icon","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[250,247,0],"ix":2,"l":2},"a":{"a":0,"k":[-81.441,794.705,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":0,"s":[550,550,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":15,"s":[360,360,100]},{"t":30,"s":[550,550,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[-2.851,0],[0,-2.851]],"o":[[0,0],[0,0],[0,-2.851],[2.851,0],[0,0]],"v":[[-76.265,790.525],[-86.617,790.525],[-86.617,787.34],[-81.441,782.164],[-76.265,787.34]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0.494,-0.366],[0,0],[0.653,0],[0,0.653],[0,0],[0,0.637],[-1.099,0],[0,0],[0,-1.099]],"o":[[0,0],[0,0.653],[-0.653,0],[0,0],[-0.462,-0.366],[0,-1.099],[0,0],[1.099,0],[0,0.653]],"v":[[-80.247,800.065],[-80.247,803.266],[-81.441,804.46],[-82.636,803.266],[-82.636,800.017],[-83.416,798.488],[-81.425,796.497],[-81.409,796.497],[-79.418,798.488]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ind":2,"ty":"sh","ix":3,"ks":{"a":0,"k":{"i":[[2.389,0.366],[0,0],[4.173,0],[0,-4.173],[0,0],[0,-2.755],[0,0],[-3.185,0],[0,0],[0,3.185],[0,0]],"o":[[0,0],[0,-4.173],[-4.173,0],[0,0],[-2.389,0.366],[0,0],[0,3.185],[0,0],[3.185,0],[0,0],[0,-2.755]],"v":[[-73.876,790.62],[-73.876,787.34],[-81.441,779.775],[-89.006,787.34],[-89.006,790.62],[-92.589,795.303],[-92.589,804.859],[-87.812,809.636],[-75.071,809.636],[-70.293,804.859],[-70.293,795.303]],"c":true},"ix":2},"nm":"Path 3","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":4,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":600,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Circle","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[250,250,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":0,"s":[530,530,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":5,"s":[520,520,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":20,"s":[550,550,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":30,"s":[520,520,100]},{"t":50,"s":[530,530,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,-16.335],[16.334,0],[0,16.334],[-16.335,0]],"o":[[0,16.334],[-16.335,0],[0,-16.335],[16.334,0]],"v":[[29.576,0],[0,29.576],[-29.576,0],[0,-29.576]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"gf","o":{"a":0,"k":100,"ix":10},"r":1,"bm":0,"g":{"p":3,"k":{"a":0,"k":[0,0.29,0.937,0.435,0.5,0.145,0.718,0.437,1,0,0.498,0.439],"ix":9}},"s":{"a":0,"k":[-11.294,-32.337],"ix":5},"e":{"a":0,"k":[9.315,28.16],"ix":6},"t":1,"nm":"Gradient Fill 1","mn":"ADBE Vector Graphic - G-Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":600,"st":0,"ct":1,"bm":0}],"markers":[],"props":{}}
|
||||
@@ -0,0 +1 @@
|
||||
{"v":"5.9.3","fr":29.9700012207031,"ip":0,"op":60.0000024438501,"w":1920,"h":1080,"nm":"1_Loading_Line","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Blue Line","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[960,539,0],"ix":2,"l":2},"a":{"a":0,"k":[0,-1,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[800,800],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.212477396049,0.540471813725,0.898039215686,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":80,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,-1],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.1],"y":[1]},"o":{"x":[0.9],"y":[0]},"t":15,"s":[0]},{"t":60.0000024438501,"s":[99.9]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.1],"y":[1]},"o":{"x":[0.9],"y":[0]},"t":0,"s":[0.01]},{"t":45.0000018328876,"s":[100]}],"ix":2},"o":{"a":0,"k":-1,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":150.000006109625,"st":0,"ct":1,"bm":0}],"markers":[{"tm":60.0000024438501,"cm":"END (No Loop)","dr":0}]}
|
||||
@@ -0,0 +1,27 @@
|
||||
//
|
||||
// ChatViewControllerWrapper.swift
|
||||
// SFI
|
||||
//
|
||||
// Created by Mac on 2024/10/24.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import UIKit
|
||||
import Crisp
|
||||
|
||||
// Step 2: Create a SwiftUI wrapper for ChatViewController
|
||||
struct ChatViewControllerWrapper: UIViewControllerRepresentable {
|
||||
|
||||
// Initialize any properties needed to pass to ChatViewController
|
||||
typealias UIViewControllerType = ChatViewController
|
||||
|
||||
func makeUIViewController(context: Context) -> ChatViewController {
|
||||
// Return the ChatViewController
|
||||
let chatViewController = ChatViewController()
|
||||
return chatViewController
|
||||
}
|
||||
|
||||
func updateUIViewController(_ uiViewController: ChatViewController, context: Context) {
|
||||
// Update the view controller when needed
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
//
|
||||
// CustomCorners.swift
|
||||
// CustomCorners
|
||||
//
|
||||
// Created by Balaji on 12/09/21.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct CustomCorners: Shape {
|
||||
|
||||
var radius: CGFloat
|
||||
var corners: UIRectCorner
|
||||
|
||||
func path(in rect: CGRect) -> Path {
|
||||
|
||||
let path = UIBezierPath(roundedRect: rect, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
|
||||
|
||||
return Path(path.cgPath)
|
||||
}
|
||||
}
|
||||
|
||||
func getSafeAreaInsets() -> UIEdgeInsets {
|
||||
let windowScene = UIApplication.shared.connectedScenes
|
||||
.filter({ $0.activationState == .foregroundActive })
|
||||
.map({ $0 as? UIWindowScene })
|
||||
.compactMap({ $0 })
|
||||
.first
|
||||
|
||||
guard let keyWindow = windowScene?.windows.filter({ $0.isKeyWindow }).first else {
|
||||
return .zero
|
||||
}
|
||||
|
||||
return keyWindow.safeAreaInsets
|
||||
}
|
||||
|
||||
|
||||
func getRect() -> CGRect {
|
||||
return UIScreen.main.bounds
|
||||
}
|
||||
@ViewBuilder
|
||||
func BackgroundBg()->some View{
|
||||
|
||||
|
||||
|
||||
ZStack{
|
||||
|
||||
LinearGradient(colors: [
|
||||
|
||||
Color("BG1"),
|
||||
Color("BG1"),
|
||||
Color("BG2"),
|
||||
Color("BG2"),
|
||||
|
||||
], startPoint: .top, endPoint: .bottom)
|
||||
|
||||
|
||||
// Little Planet and little stars....
|
||||
Image("mars")
|
||||
.resizable()
|
||||
.aspectRatio(contentMode: .fill)
|
||||
.frame(width: 30, height: 30)
|
||||
.scaleEffect(getRect().height < 750 ? 0.8 : 1)
|
||||
// not using offset...
|
||||
// using postiton..
|
||||
// this will position the object using screen basis...
|
||||
.position(x: 50, y: getRect().height < 750 ? 200 : 220)
|
||||
.opacity(0.7)
|
||||
|
||||
// Sample star points....
|
||||
let stars: [CGPoint] = [
|
||||
|
||||
CGPoint(x: 15, y: 190),
|
||||
CGPoint(x: 25, y: 250),
|
||||
CGPoint(x: 20, y: 350),
|
||||
CGPoint(x: getRect().width - 30, y: 240),
|
||||
]
|
||||
|
||||
ForEach(stars,id: \.x){star in
|
||||
|
||||
Circle()
|
||||
.fill(.white.opacity(0.3))
|
||||
.frame(width: 5, height: 5)
|
||||
.position(star)
|
||||
.offset(y: getRect().height < 750 ? -20 : 0)
|
||||
}
|
||||
|
||||
Spacer()
|
||||
|
||||
}
|
||||
.ignoresSafeArea()
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
//
|
||||
// HTMLTextView.swift
|
||||
// SFI
|
||||
//
|
||||
// Created by Mac on 2024/10/27.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import SwiftUI
|
||||
import UIKit
|
||||
|
||||
struct HTMLTextView: UIViewRepresentable {
|
||||
let htmlString: String
|
||||
|
||||
func makeUIView(context: Context) -> UITextView {
|
||||
let textView = UITextView()
|
||||
textView.isEditable = false
|
||||
textView.isScrollEnabled = true
|
||||
textView.backgroundColor = .clear
|
||||
return textView
|
||||
}
|
||||
|
||||
func updateUIView(_ uiView: UITextView, context: Context) {
|
||||
guard let data = htmlString.data(using: .utf8) else { return }
|
||||
do {
|
||||
|
||||
let attributedString = try NSAttributedString(data: data, options: [.documentType: NSAttributedString.DocumentType.html, .characterEncoding: String.Encoding.utf8.rawValue], documentAttributes: nil)
|
||||
uiView.attributedText = attributedString
|
||||
} catch {
|
||||
print("Error loading HTML: \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
//
|
||||
// CustomTF.swift
|
||||
// LoginKit
|
||||
//
|
||||
// Created by Balaji on 04/08/23.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct CustomTF: View {
|
||||
var sfIcon: String
|
||||
var iconTint: Color = .gray
|
||||
var hint: String
|
||||
/// Hides TextField
|
||||
var isPassword: Bool = false
|
||||
var hasDriveLine: Bool = true
|
||||
|
||||
|
||||
@Binding var value: String
|
||||
/// View Properties
|
||||
@State private var showPassword: Bool = false
|
||||
/// When Switching Between Hide/Reveal Password Field, The Keyboard is Closing, to avoid that using the FocusState
|
||||
@FocusState private var passwordState: HideState?
|
||||
|
||||
enum HideState {
|
||||
case hide
|
||||
case reveal
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
HStack(alignment: .top, spacing: 8, content: {
|
||||
Image(systemName: sfIcon)
|
||||
.foregroundStyle(iconTint)
|
||||
/// Since I Need Same Width to Align TextFields Equally
|
||||
.frame(width: 30)
|
||||
/// Slightly Bringing Down
|
||||
.offset(y: 2)
|
||||
|
||||
VStack(alignment: .leading, spacing: 8, content: {
|
||||
if isPassword {
|
||||
Group {
|
||||
/// Revealing Password when users wants to show Password
|
||||
if showPassword {
|
||||
TextField(hint, text: $value)
|
||||
.focused($passwordState, equals: .reveal)
|
||||
} else {
|
||||
SecureField(hint, text: $value)
|
||||
.focused($passwordState, equals: .hide)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
TextField(hint, text: $value)
|
||||
}
|
||||
|
||||
if hasDriveLine {
|
||||
Divider()
|
||||
}
|
||||
|
||||
})
|
||||
.overlay(alignment: .trailing) {
|
||||
/// Password Reveal Button
|
||||
if isPassword {
|
||||
Button(action: {
|
||||
withAnimation {
|
||||
showPassword.toggle()
|
||||
}
|
||||
passwordState = showPassword ? .reveal : .hide
|
||||
}, label: {
|
||||
Image(systemName: showPassword ? "eye.slash" : "eye")
|
||||
.foregroundStyle(.gray)
|
||||
.padding(10)
|
||||
.contentShape(.rect)
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
//
|
||||
// GradientButton.swift
|
||||
// LoginKit
|
||||
//
|
||||
// Created by Balaji on 04/08/23.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct GradientButton: View {
|
||||
var title: String
|
||||
var icon: String
|
||||
var onClick: () -> ()
|
||||
var body: some View {
|
||||
Button(action: onClick, label: {
|
||||
HStack(spacing: 15) {
|
||||
Text(title)
|
||||
Image(systemName: icon)
|
||||
}
|
||||
////.fontWeight(.bold)
|
||||
.foregroundStyle(.white)
|
||||
.padding(.vertical, 12)
|
||||
.padding(.horizontal, 35)
|
||||
.background(.linearGradient(colors: [.main, .main2, ], startPoint: .top, endPoint: .bottom), in: .capsule)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
//
|
||||
// OTPVerificationView.swift
|
||||
// AutoOtpTF
|
||||
//
|
||||
// Created by Balaji on 23/12/22.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct OTPVerificationView: View {
|
||||
/// - View Properties
|
||||
@Binding var otpText: String
|
||||
/// - Keyboard State
|
||||
@FocusState private var isKeyboardShowing: Bool
|
||||
var body: some View {
|
||||
HStack(spacing: 0){
|
||||
/// - OTP Text Boxes
|
||||
/// Change Count Based on your OTP Text Size
|
||||
ForEach(0..<6,id: \.self){index in
|
||||
OTPTextBox(index)
|
||||
}
|
||||
}
|
||||
.background(content: {
|
||||
TextField("", text: $otpText.limit(6))
|
||||
.keyboardType(.numberPad)
|
||||
.textContentType(.oneTimeCode)
|
||||
/// - Hiding it Out
|
||||
.frame(width: 1, height: 1)
|
||||
.opacity(0.001)
|
||||
.blendMode(.screen)
|
||||
.focused($isKeyboardShowing)
|
||||
})
|
||||
.contentShape(Rectangle())
|
||||
/// - Opening Keyboard When Tapped
|
||||
.onTapGesture {
|
||||
isKeyboardShowing = true
|
||||
}
|
||||
.toolbar {
|
||||
ToolbarItem(placement: .keyboard) {
|
||||
Button("Done"){
|
||||
isKeyboardShowing = false
|
||||
}
|
||||
.tint(.white)
|
||||
////.fontWeight(.heavy)
|
||||
.hSpacing(.trailing)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: OTP Text Box
|
||||
@ViewBuilder
|
||||
func OTPTextBox(_ index: Int)->some View{
|
||||
ZStack{
|
||||
if otpText.count > index{
|
||||
/// - Finding Char At Index
|
||||
let startIndex = otpText.startIndex
|
||||
let charIndex = otpText.index(startIndex, offsetBy: index)
|
||||
let charToString = String(otpText[charIndex])
|
||||
Text(charToString)
|
||||
}else{
|
||||
Text(" ")
|
||||
}
|
||||
}
|
||||
.frame(width: 45, height: 45)
|
||||
.background {
|
||||
/// - Highlighting Current Active Box
|
||||
let status = (isKeyboardShowing && otpText.count == index)
|
||||
RoundedRectangle(cornerRadius: 6, style: .continuous)
|
||||
.stroke(status ? .main : Color.gray,lineWidth: status ? 3 : 0.5)
|
||||
/// - Adding Animation
|
||||
.animation(.easeInOut(duration: 0.2), value: isKeyboardShowing)
|
||||
}
|
||||
.frame(maxWidth: .infinity)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Binding <String> Extension
|
||||
extension Binding where Value == String{
|
||||
func limit(_ length: Int)->Self{
|
||||
if self.wrappedValue.count > length{
|
||||
DispatchQueue.main.async {
|
||||
self.wrappedValue = String(self.wrappedValue.prefix(length))
|
||||
}
|
||||
}
|
||||
return self
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
//
|
||||
// LottieView.swift
|
||||
// VPNUI
|
||||
//
|
||||
// Created by Mac on 2024/9/26.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
//import Lottie
|
||||
import SwiftUI
|
||||
import Lottie
|
||||
|
||||
struct LottieView: UIViewRepresentable {
|
||||
|
||||
var animationFileName: String
|
||||
let loopMode: LottieLoopMode
|
||||
|
||||
func updateUIView(_ uiView: UIViewType, context: Context) {
|
||||
|
||||
}
|
||||
|
||||
func makeUIView(context: Context) -> Lottie.LottieAnimationView {
|
||||
let animationView = LottieAnimationView(name: animationFileName)
|
||||
animationView.loopMode = loopMode
|
||||
animationView.play()
|
||||
animationView.contentMode = .scaleAspectFit
|
||||
|
||||
return animationView
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
//
|
||||
// Unitity.swift
|
||||
// SFI
|
||||
//
|
||||
// Created by Mac on 2024/10/20.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
struct TimestampConverter {
|
||||
|
||||
// Function to convert a timestamp to a formatted date string
|
||||
static func convertTimestampToDateString(_ timestamp: Int, format: String = "yyyy-MM-dd HH:mm:ss") -> String {
|
||||
let timeInterval = TimeInterval(timestamp)
|
||||
let date = Date(timeIntervalSince1970: timeInterval)
|
||||
let dateFormatter = DateFormatter()
|
||||
dateFormatter.dateFormat = format
|
||||
return dateFormatter.string(from: date)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
//
|
||||
// UniversalAlert.swift
|
||||
// CustomUniversalAlert
|
||||
//
|
||||
// Created by Balaji Venkatesh on 18/09/23.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
/// Alert Config
|
||||
struct AlertConfig {
|
||||
fileprivate var enableBackgroundBlur: Bool = true
|
||||
fileprivate var disableOutsideTap: Bool = true
|
||||
fileprivate var transitionType: TransitionType = .slide
|
||||
fileprivate var slideEdge: Edge = .bottom
|
||||
fileprivate var show: Bool = false
|
||||
fileprivate var showView: Bool = false
|
||||
|
||||
init(enableBackgroundBlur: Bool = true, disableOutsideTap: Bool = true, transitionType: TransitionType = .slide, slideEdge: Edge = .bottom) {
|
||||
self.enableBackgroundBlur = enableBackgroundBlur
|
||||
self.disableOutsideTap = disableOutsideTap
|
||||
self.transitionType = transitionType
|
||||
self.slideEdge = slideEdge
|
||||
}
|
||||
|
||||
/// TransitionType
|
||||
enum TransitionType {
|
||||
case slide
|
||||
case opacity
|
||||
}
|
||||
|
||||
/// Alert Present/Dismiss Methods
|
||||
mutating
|
||||
func present() {
|
||||
show = true
|
||||
}
|
||||
|
||||
mutating
|
||||
func dismiss() {
|
||||
show = false
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
fileprivate struct AlertView<Content: View>: View {
|
||||
@Binding var config: AlertConfig
|
||||
/// View Tag
|
||||
var tag: Int
|
||||
@ViewBuilder var content: () -> Content
|
||||
/// View Properties
|
||||
@State private var showView: Bool = false
|
||||
var body: some View {
|
||||
GeometryReader(content: { geometry in
|
||||
if showView && config.transitionType == .slide {
|
||||
content()
|
||||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||
.transition(.move(edge: config.slideEdge))
|
||||
} else {
|
||||
content()
|
||||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||
.opacity(showView ? 1 : 0)
|
||||
}
|
||||
})
|
||||
.background {
|
||||
ZStack {
|
||||
if config.enableBackgroundBlur {
|
||||
Rectangle()
|
||||
.fill(.ultraThinMaterial)
|
||||
} else {
|
||||
Rectangle()
|
||||
.fill(.primary.opacity(0.25))
|
||||
}
|
||||
}
|
||||
.ignoresSafeArea()
|
||||
.contentShape(.rect)
|
||||
.onTapGesture {
|
||||
if !config.disableOutsideTap {
|
||||
config.dismiss()
|
||||
}
|
||||
}
|
||||
.opacity(showView ? 1 : 0)
|
||||
}
|
||||
.onAppear(perform: {
|
||||
config.showView = true
|
||||
})
|
||||
// .onChange(of: config.showView) { oldValue, newValue in
|
||||
// withAnimation(.smooth(duration: 0.35, extraBounce: 0)) {
|
||||
// showView = newValue
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,190 @@
|
||||
//
|
||||
// View+Extensions.swift
|
||||
// LoginKit
|
||||
//
|
||||
// Created by Balaji on 04/08/23.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
/// Custom SwiftUI View Extensions
|
||||
extension View {
|
||||
/// View Alignments
|
||||
@ViewBuilder
|
||||
func hSpacing(_ alignment: Alignment = .center) -> some View {
|
||||
self
|
||||
.frame(maxWidth: .infinity, alignment: alignment)
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
func vSpacing(_ alignment: Alignment = .center) -> some View {
|
||||
self
|
||||
.frame(maxHeight: .infinity, alignment: alignment)
|
||||
}
|
||||
|
||||
/// Disable With Opacity
|
||||
@ViewBuilder
|
||||
func disableWithOpacity(_ condition: Bool) -> some View {
|
||||
self
|
||||
.disabled(condition)
|
||||
.opacity(condition ? 0.5 : 1)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Extedning View to get Screen Size and Frame....
|
||||
extension View{
|
||||
|
||||
func getRect()->CGRect{
|
||||
UIScreen.main.bounds
|
||||
}
|
||||
|
||||
func getSafeArea()->UIEdgeInsets{
|
||||
guard let screen = UIApplication.shared.connectedScenes.first as? UIWindowScene else{
|
||||
return .zero
|
||||
}
|
||||
|
||||
guard let safeArea = screen.windows.first?.safeAreaInsets else{
|
||||
return .zero
|
||||
}
|
||||
|
||||
return safeArea
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
extension Text {
|
||||
init(_ attributedString: NSAttributedString) {
|
||||
self.init("") // initial, empty Text
|
||||
|
||||
// scan the attributed string for distinctly attributed regions
|
||||
attributedString.enumerateAttributes(in: NSRange(location: 0, length: attributedString.length),
|
||||
options: []) { (attrs, range, _) in
|
||||
let string = attributedString.attributedSubstring(from: range).string
|
||||
var text = Text(string)
|
||||
|
||||
// then, read applicable attributes and apply them to the Text
|
||||
|
||||
if let font = attrs[.font] as? UIFont {
|
||||
// this takes care of the majority of formatting - text size, font family,
|
||||
// font weight, if it's italic, etc.
|
||||
text = text.font(.init(font))
|
||||
}
|
||||
|
||||
if let color = attrs[.foregroundColor] as? UIColor {
|
||||
text = text.foregroundColor(Color(color))
|
||||
}
|
||||
|
||||
if let kern = attrs[.kern] as? CGFloat {
|
||||
text = text.kerning(kern)
|
||||
}
|
||||
|
||||
if #available(iOS 14.0, *) {
|
||||
if let tracking = attrs[.tracking] as? CGFloat {
|
||||
text = text.tracking(tracking)
|
||||
}
|
||||
}
|
||||
|
||||
if let strikethroughStyle = attrs[.strikethroughStyle] as? NSNumber,
|
||||
strikethroughStyle != 0 {
|
||||
if let strikethroughColor = (attrs[.strikethroughColor] as? UIColor) {
|
||||
text = text.strikethrough(true, color: Color(strikethroughColor))
|
||||
} else {
|
||||
text = text.strikethrough(true)
|
||||
}
|
||||
}
|
||||
|
||||
if let underlineStyle = attrs[.underlineStyle] as? NSNumber,
|
||||
underlineStyle != 0 {
|
||||
if let underlineColor = (attrs[.underlineColor] as? UIColor) {
|
||||
text = text.underline(true, color: Color(underlineColor))
|
||||
} else {
|
||||
text = text.underline(true)
|
||||
}
|
||||
}
|
||||
|
||||
if let baselineOffset = attrs[.baselineOffset] as? NSNumber {
|
||||
text = text.baselineOffset(CGFloat(baselineOffset.floatValue))
|
||||
}
|
||||
|
||||
// append the newly styled subtext to the rest of the text
|
||||
self = self + text
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
extension Text {
|
||||
init(html htmlString: String, // the HTML-formatted string
|
||||
raw: Bool = false, // set to true if you don't want to embed in the doc skeleton
|
||||
size: CGFloat? = nil, // optional document-wide text size
|
||||
fontFamily: String = "-apple-system") { // optional document-wide font family
|
||||
let fullHTML: String
|
||||
if raw {
|
||||
fullHTML = htmlString
|
||||
} else {
|
||||
var sizeCss = ""
|
||||
if let size = size {
|
||||
sizeCss = "font-size: \(size)px;"
|
||||
}
|
||||
fullHTML = """
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<style>
|
||||
body {
|
||||
font-family: \(fontFamily);
|
||||
\(sizeCss)
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
\(htmlString)
|
||||
</body>
|
||||
</html>
|
||||
"""
|
||||
}
|
||||
let attributedString: NSAttributedString
|
||||
if let data = fullHTML.data(using: .unicode),
|
||||
let attrString = try? NSAttributedString(data: data,
|
||||
options: [.documentType: NSAttributedString.DocumentType.html],
|
||||
documentAttributes: nil) {
|
||||
attributedString = attrString
|
||||
} else {
|
||||
attributedString = NSAttributedString()
|
||||
}
|
||||
|
||||
self.init(attributedString) // uses the NSAttributedString initializer
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public extension View {
|
||||
// 扩展 View 以提供隐藏键盘的功能
|
||||
func hideKeyboard() {
|
||||
UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
|
||||
}
|
||||
func transparentScrolling() -> some View {
|
||||
if #available(iOS 16.0, *) {
|
||||
return scrollContentBackground(.hidden)
|
||||
} else {
|
||||
return onAppear {
|
||||
UITextView.appearance().backgroundColor = .clear
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct TriangleShape: Shape {
|
||||
func path(in rect: CGRect) -> Path {
|
||||
var path = Path()
|
||||
path.move(to: CGPoint(x: rect.minX, y: rect.minY))
|
||||
path.addLine(to: CGPoint(x: rect.maxX, y: rect.midY))
|
||||
path.addLine(to: CGPoint(x: rect.minX, y: rect.maxY))
|
||||
path.closeSubpath()
|
||||
return path
|
||||
}
|
||||
}
|
||||
|
||||