Skip to content

Commit

Permalink
refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
grdsdev committed Jul 15, 2024
1 parent b8b0c60 commit dac2136
Show file tree
Hide file tree
Showing 3 changed files with 170 additions and 75 deletions.
8 changes: 8 additions & 0 deletions Examples/Examples.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
79615DF92C3DA92C005AE6E0 /* CustomDump in Frameworks */ = {isa = PBXBuildFile; productRef = 79615DF82C3DA92C005AE6E0 /* CustomDump */; };
796298992AEBBA77000AA957 /* MFAFlow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 796298982AEBBA77000AA957 /* MFAFlow.swift */; };
7962989D2AEBC6F9000AA957 /* SVGView in Frameworks */ = {isa = PBXBuildFile; productRef = 7962989C2AEBC6F9000AA957 /* SVGView */; };
796B32BE2C4559E900DDD7B4 /* IdentifiedCollections in Frameworks */ = {isa = PBXBuildFile; productRef = 796B32BD2C4559E900DDD7B4 /* IdentifiedCollections */; };
79719ECE2ADF26C400737804 /* Supabase in Frameworks */ = {isa = PBXBuildFile; productRef = 79719ECD2ADF26C400737804 /* Supabase */; };
797D664A2B46A1D8007592ED /* Dependencies.swift in Sources */ = {isa = PBXBuildFile; fileRef = 797D66492B46A1D8007592ED /* Dependencies.swift */; };
797EFB662BABD82A00098D6B /* BucketList.swift in Sources */ = {isa = PBXBuildFile; fileRef = 797EFB652BABD82A00098D6B /* BucketList.swift */; };
Expand Down Expand Up @@ -163,6 +164,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
796B32BE2C4559E900DDD7B4 /* IdentifiedCollections in Frameworks */,
792404E32C3473EC002959B3 /* Supabase in Frameworks */,
79615DF92C3DA92C005AE6E0 /* CustomDump in Frameworks */,
);
Expand Down Expand Up @@ -403,6 +405,7 @@
packageProductDependencies = (
792404E22C3473EC002959B3 /* Supabase */,
79615DF82C3DA92C005AE6E0 /* CustomDump */,
796B32BD2C4559E900DDD7B4 /* IdentifiedCollections */,
);
productName = SupaDrive;
productReference = 792404B72C3454A9002959B3 /* SupaDrive.app */;
Expand Down Expand Up @@ -1191,6 +1194,11 @@
package = 7962989B2AEBC6F9000AA957 /* XCRemoteSwiftPackageReference "SVGView" */;
productName = SVGView;
};
796B32BD2C4559E900DDD7B4 /* IdentifiedCollections */ = {
isa = XCSwiftPackageProductDependency;
package = 7956406E2955B5190088A06F /* XCRemoteSwiftPackageReference "swift-identified-collections" */;
productName = IdentifiedCollections;
};
79719ECD2ADF26C400737804 /* Supabase */ = {
isa = XCSwiftPackageProductDependency;
productName = Supabase;
Expand Down
233 changes: 159 additions & 74 deletions Examples/SupaDrive/AppView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,58 +8,98 @@
import CustomDump
import Supabase
import SwiftUI
import IdentifiedCollections

@MainActor
@Observable
final class AppModel {
var panels: IdentifiedArrayOf<PanelModel> {
didSet {
bindPanelModels()
}
}

struct AppView: View {
@State var path: [String]
@State var selectedItemPerPath: [String: FileObject] = [:]
init(panels: IdentifiedArrayOf<PanelModel>) {
self.panels = panels
bindPanelModels()
}

var path: String {
panels.last?.path ?? ""
}

var pathComponents: [String] {
path.components(separatedBy: "/")
}

var selectedFile: FileObject? {
panels.last?.selectedItem
}

private func bindPanelModels() {
for panel in panels {
panel.onSelectItem = { [weak self, weak panel] item in
guard let self, let panel else { return }

// self.panels.append(PanelModel(path: self.path.appending))
//
// if let name = item.name, item.id == nil {
// self.panels.replaceSubrange(
// (index + 1)...,
// with: [PanelModel(path: self.path.appending("/\(name)"))]
// )
// }
}
}
}
}

@State var reload = UUID()
struct AppView: View {
@Bindable var model: AppModel

var body: some View {
VStack(alignment: .leading, spacing: 0) {
breadcrump

ScrollView(.horizontal) {
HStack {
ForEach(path.indices, id: \.self) { pathIndex in
ForEach(model.panels) { panel in
PanelView(
path: path[0 ... pathIndex].joined(separator: "/"),
selectedItem: Binding(
get: {
selectedItemPerPath[path[pathIndex]]
},
set: { newValue in
selectedItemPerPath[path[pathIndex]] = newValue

if let newValue, let name = newValue.name, newValue.id == nil {
path.replaceSubrange((pathIndex + 1)..., with: [name])
} else {
path.replaceSubrange((pathIndex + 1)..., with: [])
}
}
)
model: panel
// model: PanelModel(path: path[0 ... pathIndex].joined(separator: "/"))
// path: path[0 ... pathIndex].joined(separator: "/"),
// selectedItem: Binding(
// get: {
// selectedItemPerPath[path[pathIndex]]
// },
// set: { newValue in
// selectedItemPerPath[path[pathIndex]] = newValue
//
// if let newValue, let name = newValue.name, newValue.id == nil {
// path.replaceSubrange((pathIndex + 1)..., with: [name])
// } else {
// path.replaceSubrange((pathIndex + 1)..., with: [])
// }
// }
// )
)
.frame(width: 200)
}
}
}
}
.overlay(alignment: .trailing) {
if
let lastPath = path.last,
let selectedItem = selectedItemPerPath[lastPath],
selectedItem.id != nil
{
if let selectedFile = model.selectedFile {
Form {
Text(selectedItem.name ?? "")
Text(selectedFile.name ?? "")
.font(.title2)
Divider()

if let contentLenth = selectedItem.metadata?["contentLength"]?.intValue {
if let contentLenth = selectedFile.metadata?["contentLength"]?.intValue {
LabeledContent("Size", value: "\(contentLenth)")
}

if let mimeType = selectedItem.metadata?["mimetype"]?.stringValue {
if let mimeType = selectedFile.metadata?["mimetype"]?.stringValue {
LabeledContent("MIME Type", value: mimeType)
}
}
Expand All @@ -70,56 +110,116 @@ struct AppView: View {
.transition(.move(edge: .trailing))
}
}
.animation(.default, value: path)
.animation(.default, value: selectedItemPerPath)
.animation(.default, value: model.path)
.animation(.default, value: model.selectedFile)
}

var breadcrump: some View {
HStack {
ForEach(Array(zip(path.indices, path)), id: \.0) { idx, path in
ForEach(Array(zip(model.pathComponents.indices, model.pathComponents)), id: \.0) { idx, path in
Button(path) {
self.path.replaceSubrange((idx + 1)..., with: [])
// self.path.replaceSubrange((idx + 1)..., with: [])
}
.buttonStyle(.plain)

if idx != self.path.indices.last {
Text(">")
}
// if idx != self.path.indices.last {
// Text(">")
// }
}
}
.padding()
}
}

struct DragValue: Codable {
let path: String
let object: FileObject
}

@MainActor
@Observable
final class PanelModel: Identifiable {
let path: String
var selectedItem: FileObject?

var items: [FileObject] = []

@ObservationIgnored
var onSelectItem: @MainActor (FileObject) -> Void = { _ in }

init(path: String) {
self.path = path
}

func load() async {
do {
let files = try await supabase.storage.from("main").list(path: path)
items = files.filter { $0.name?.hasPrefix(".") == false }
} catch {
dump(error)
}
}

func didSelectItem(_ item: FileObject) {
self.selectedItem = item
onSelectItem(item)
}

func newFolderButtonTapped() async {
do {
try await supabase.storage.from("main")
.upload(path: "\(path)/Untiltled/.dummy", file: Data())
} catch {

}
}

func uploadFile(at url: URL) async {
let path = url.lastPathComponent

do {
let file = try Data(contentsOf: url)
try await supabase.storage.from("main")
.upload(path: "\(self.path)/\(path)", file: file)
} catch {}
}
}

struct PanelView: View {
var path: String
@Binding var selectedItem: FileObject?
@Bindable var model: PanelModel

@State private var isDraggingOver = false
@State private var items: [FileObject] = []

@State private var reload = UUID()

var body: some View {
List {
ForEach(items) { item in
Button {
selectedItem = item
} label: {
Text(item.name ?? "")
.bold(selectedItem == item)
ForEach(model.items) { item in
Text(item.name ?? "")
.bold(model.selectedItem == item)
.onTapGesture {
model.didSelectItem(item)
}
.onDrag {
let data = try! JSONEncoder().encode(DragValue(path: model.path, object: item))
let string = String(decoding: data, as: UTF8.self)
return NSItemProvider(object: string as NSString)
}
}
.onInsert(of: ["public.text"]) { index, items in
for item in items {
Task {
guard let data = try await item.loadItem(forTypeIdentifier: "public.text") as? Data,
let value = try? JSONDecoder().decode(DragValue.self, from: data) else {
return
}

self.model.items.insert(value.object, at: index)
}
}
print(index, items)
}
.buttonStyle(.plain)
}
.task(id: reload) {
do {
let files = try await supabase.storage.from("main").list(path: path)

items = files.filter { $0.name?.hasPrefix(".") == false }
} catch {
dump(error)
}
.task {
await model.load()
}
.onDrop(of: [.fileURL], isTargeted: $isDraggingOver) { providers in
for provider in providers {
Expand All @@ -128,13 +228,8 @@ struct PanelView: View {
return
}

Task { @MainActor in
let path = url.lastPathComponent
let file = try! Data(contentsOf: url)
try! await supabase.storage.from("main")
.upload(path: "\(self.path)/\(path)", file: file)

reload = UUID()
Task {
await model.uploadFile(at: url)
}
}
}
Expand All @@ -148,23 +243,13 @@ struct PanelView: View {
.contextMenu {
Button("New folder") {
Task {
try! await supabase.storage.from("main")
.upload(path: "\(path)/Untiltled/.dummy", file: Data())
reload = UUID()
await model.newFolderButtonTapped()
}
}
}
}
}

extension FileObject {
var metadataDump: String {
var output = ""
customDump(metadata, to: &output)
return output
}
}

#Preview {
AppView(path: [])
AppView(model: AppModel(panels: []))
}
4 changes: 3 additions & 1 deletion Examples/SupaDrive/SupaDriveApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ struct SupaDriveApp: App {
var body: some Scene {
WindowGroup {
AuthView { session in
AppView(path: [session.user.id.uuidString.lowercased()])
AppView(
model: AppModel(panels: [PanelModel(path: session.user.id.uuidString.lowercased())])
)
}
}
}
Expand Down

0 comments on commit dac2136

Please sign in to comment.