Skip to content

Commit

Permalink
feat: Show a document preview in the rule wizard on iOS (#484)
Browse files Browse the repository at this point in the history
  • Loading branch information
jbmorley authored Nov 27, 2022
1 parent 234e501 commit 5f8ec17
Show file tree
Hide file tree
Showing 9 changed files with 205 additions and 54 deletions.
21 changes: 1 addition & 20 deletions core/Sources/FileawayCore/Views/Wizard/RuleForm.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,36 +24,17 @@ public struct RuleForm: View {

@ObservedObject private var ruleFormModel: RuleFormModel
private let url: URL
@StateObject private var dateExtractor: DateExtractor

public init(_ ruleFormModel: RuleFormModel, url: URL) {
self.ruleFormModel = ruleFormModel
self.url = url
_dateExtractor = StateObject(wrappedValue: DateExtractor(url: url))
}

public var body: some View {
Form {
Section {
ForEach(ruleFormModel.variableFieldModels) { variable in
if let variable = variable as? DateFieldModel {
DateField(variable: variable,
creationDate: FileInfo.creationDate(url: url)?.date,
options: dateExtractor.dates)
} else if let variable = variable as? StringFieldModel {
StringField(variable: variable)
} else {
Text("Unknown Variable Type")
}
}
} footer: {
Text(ruleFormModel.attributedRelativeDestinationPath(font: .standardizedFooter))
.horizontalSpace(.trailing)
}
RuleFormSection(ruleFormModel, url: url)
}
.formStyle(.grouped)
.runs(ruleFormModel)
.runs(dateExtractor)
}

}
64 changes: 64 additions & 0 deletions core/Sources/FileawayCore/Views/Wizard/RuleFormSection.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// Copyright (c) 2018-2022 InSeven Limited
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

import SwiftUI

import Interact

extension String: Identifiable {

public var id: Self { self }

}

public struct RuleFormSection: View {

@ObservedObject private var ruleFormModel: RuleFormModel
private let url: URL
@StateObject private var dateExtractor: DateExtractor

public init(_ ruleFormModel: RuleFormModel, url: URL) {
self.ruleFormModel = ruleFormModel
self.url = url
_dateExtractor = StateObject(wrappedValue: DateExtractor(url: url))
}

public var body: some View {
Section {
ForEach(ruleFormModel.variableFieldModels) { variable in
if let variable = variable as? DateFieldModel {
DateField(variable: variable,
creationDate: FileInfo.creationDate(url: url)?.date,
options: dateExtractor.dates)
} else if let variable = variable as? StringFieldModel {
StringField(variable: variable)
} else {
Text("Unknown Variable Type")
}
}
} footer: {
Text(ruleFormModel.attributedRelativeDestinationPath(font: .standardizedFooter))
.horizontalSpace(.trailing)
}
.runs(ruleFormModel)
.runs(dateExtractor)
}

}
2 changes: 1 addition & 1 deletion interact
26 changes: 21 additions & 5 deletions ios/Fileaway-iOS.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
D81C5D93249BE3710083BD6F /* RulesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D81C5D92249BE3710083BD6F /* RulesView.swift */; };
D81C5D95249BE6F40083BD6F /* RuleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D81C5D94249BE6F40083BD6F /* RuleView.swift */; };
D85067FA292B8DE80017865A /* FileTypesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D85067F9292B8DE80017865A /* FileTypesView.swift */; };
D850BD3329333E3800D81AAA /* DocumentPreviewHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = D850BD3229333E3800D81AAA /* DocumentPreviewHeader.swift */; };
D850BD3629333FF300D81AAA /* CGSize.swift in Sources */ = {isa = PBXBuildFile; fileRef = D850BD3529333FF300D81AAA /* CGSize.swift */; };
D85532A0291E5FB400C21E12 /* WizardView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D855329F291E5FB400C21E12 /* WizardView.swift */; };
D864870D292CB99C007CD688 /* AddFileTypesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D864870C292CB99C007CD688 /* AddFileTypesView.swift */; };
D8648710292CD08F007CD688 /* WizardModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D864870F292CD08F007CD688 /* WizardModel.swift */; };
Expand All @@ -33,7 +35,7 @@
D8E4CA5D249D061D00F5BC8E /* EditableText.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8E4CA5C249D061D00F5BC8E /* EditableText.swift */; };
D8F763DA292259960051D740 /* RulePicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8F763D9292259960051D740 /* RulePicker.swift */; };
D8F763DC29225F720051D740 /* RuleFormView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8F763DB29225F720051D740 /* RuleFormView.swift */; };
D8F763DE29226FD30051D740 /* FilePreviewHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8F763DD29226FD30051D740 /* FilePreviewHeader.swift */; };
D8F763DE29226FD30051D740 /* DocumentPreviewButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8F763DD29226FD30051D740 /* DocumentPreviewButton.swift */; };
D8FB857F2916D2430024F885 /* Diligence in Frameworks */ = {isa = PBXBuildFile; productRef = D8FB857E2916D2430024F885 /* Diligence */; };
D8FB85822916D31D0024F885 /* AboutView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8FB85812916D31D0024F885 /* AboutView.swift */; };
/* End PBXBuildFile section */
Expand All @@ -59,6 +61,8 @@
D81C5D92249BE3710083BD6F /* RulesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RulesView.swift; sourceTree = "<group>"; };
D81C5D94249BE6F40083BD6F /* RuleView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuleView.swift; sourceTree = "<group>"; };
D85067F9292B8DE80017865A /* FileTypesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileTypesView.swift; sourceTree = "<group>"; };
D850BD3229333E3800D81AAA /* DocumentPreviewHeader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DocumentPreviewHeader.swift; sourceTree = "<group>"; };
D850BD3529333FF300D81AAA /* CGSize.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CGSize.swift; sourceTree = "<group>"; };
D855329F291E5FB400C21E12 /* WizardView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WizardView.swift; sourceTree = "<group>"; };
D864870C292CB99C007CD688 /* AddFileTypesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddFileTypesView.swift; sourceTree = "<group>"; };
D864870F292CD08F007CD688 /* WizardModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WizardModel.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -88,7 +92,7 @@
D8E4CA5C249D061D00F5BC8E /* EditableText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditableText.swift; sourceTree = "<group>"; };
D8F763D9292259960051D740 /* RulePicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RulePicker.swift; sourceTree = "<group>"; };
D8F763DB29225F720051D740 /* RuleFormView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuleFormView.swift; sourceTree = "<group>"; };
D8F763DD29226FD30051D740 /* FilePreviewHeader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FilePreviewHeader.swift; sourceTree = "<group>"; };
D8F763DD29226FD30051D740 /* DocumentPreviewButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DocumentPreviewButton.swift; sourceTree = "<group>"; };
D8FB85812916D31D0024F885 /* AboutView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AboutView.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */

Expand Down Expand Up @@ -134,6 +138,14 @@
path = Views;
sourceTree = "<group>";
};
D850BD3429333FE600D81AAA /* Extensions */ = {
isa = PBXGroup;
children = (
D850BD3529333FF300D81AAA /* CGSize.swift */,
);
path = Extensions;
sourceTree = "<group>";
};
D864870E292CCF2D007CD688 /* Model */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -187,6 +199,7 @@
D8CCB8112143672700AC445F /* Info.plist */,
D8C15DB9291A498F002DB14D /* FileawayApp.swift */,
D8CCB80C2143672700AC445F /* Assets.xcassets */,
D850BD3429333FE600D81AAA /* Extensions */,
D8CCB80E2143672700AC445F /* LaunchScreen.storyboard */,
D864870E292CCF2D007CD688 /* Model */,
D81C5D8F249BDD3C0083BD6F /* Views */,
Expand Down Expand Up @@ -236,11 +249,12 @@
D8F763D5292255780051D740 /* Wizard */ = {
isa = PBXGroup;
children = (
D8F763DD29226FD30051D740 /* FilePreviewHeader.swift */,
D8F763DD29226FD30051D740 /* DocumentPreviewButton.swift */,
D850BD3229333E3800D81AAA /* DocumentPreviewHeader.swift */,
D8F763DB29225F720051D740 /* RuleFormView.swift */,
D8F763D9292259960051D740 /* RulePicker.swift */,
D855329F291E5FB400C21E12 /* WizardView.swift */,
D8648711292D323A007CD688 /* RulePickerRow.swift */,
D855329F291E5FB400C21E12 /* WizardView.swift */,
);
path = Wizard;
sourceTree = "<group>";
Expand Down Expand Up @@ -415,10 +429,12 @@
buildActionMask = 2147483647;
files = (
D8D81EB2291DD07800870E6E /* VariableView.swift in Sources */,
D850BD3329333E3800D81AAA /* DocumentPreviewHeader.swift in Sources */,
D850BD3629333FF300D81AAA /* CGSize.swift in Sources */,
D8FB85822916D31D0024F885 /* AboutView.swift in Sources */,
D85532A0291E5FB400C21E12 /* WizardView.swift in Sources */,
D8D81EB4291DD1BE00870E6E /* DestinationFooter.swift in Sources */,
D8F763DE29226FD30051D740 /* FilePreviewHeader.swift in Sources */,
D8F763DE29226FD30051D740 /* DocumentPreviewButton.swift in Sources */,
D8A871D22916D56400B2932A /* ComponentItem.swift in Sources */,
D8F763DC29225F720051D740 /* RuleFormView.swift in Sources */,
D8D81EB0291DC70200870E6E /* ContentView.swift in Sources */,
Expand Down
27 changes: 27 additions & 0 deletions ios/Fileaway/Extensions/CGSize.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright (c) 2018-2022 InSeven Limited
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

import CoreGraphics

extension CGSize {

static let navigationBarIcon = CGSize(width: 32.0, height: 32.0)

}
Original file line number Diff line number Diff line change
Expand Up @@ -20,26 +20,29 @@

import SwiftUI

import Interact

import FileawayCore

struct FilePreviewHeader: ToolbarContent {
public struct DocumentPreviewButton: View {

@State private var previewURL: URL?

private let url: URL
private let size: CGSize

init(url: URL) {
init(url: URL, size: CGSize) {
self.url = url
self.size = size
}

var body: some ToolbarContent {
ToolbarItem(placement: .principal) {
Button("Preview") {
previewURL = url
}
.buttonStyle(.borderedProminent)
.quickLookPreview($previewURL)
public var body: some View {
Button() {
previewURL = url
} label: {
IconView(url: url, size: size)
}
.quickLookPreview($previewURL)
}

}
48 changes: 48 additions & 0 deletions ios/Fileaway/Views/Wizard/DocumentPreviewHeader.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// Copyright (c) 2018-2022 InSeven Limited
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

import SwiftUI

import Interact

import FileawayCore

struct DocumentPreviewHeader: View {

@Binding private var isVisible: Bool
private let url: URL

init(_ isVisible: Binding<Bool>, url: URL) {
_isVisible = isVisible
self.url = url
}

var body: some View {
ConditionalHeader($isVisible) {
DocumentPreviewButton(url: url, size: .init(width: 240, height: 240))
.horizontalSpace(.both)
Text(url.displayName)
.font(.body)
.fontWeight(.bold)
.multilineTextAlignment(.center)
}
}

}
38 changes: 22 additions & 16 deletions ios/Fileaway/Views/Wizard/RuleFormView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,12 @@ import FileawayCore

struct RuleFormView: View {

@EnvironmentObject var wizardModel: WizardModel

@ObservedObject var ruleModel: RuleModel

@StateObject var ruleFormModel: RuleFormModel
@EnvironmentObject var wizardModel: WizardModel
@State private var isHeaderVisible: Bool = true

var url: URL

Expand All @@ -39,24 +42,27 @@ struct RuleFormView: View {
}

var body: some View {
RuleForm(ruleFormModel, url: url)
.navigationTitle(ruleFormModel.name)
.toolbar {

FilePreviewHeader(url: url)

ToolbarItem(placement: .navigationBarTrailing) {
Button("Move") {
do {
try ruleFormModel.move()
wizardModel.complete()
} catch {
// TODO: Present this error to the user.
print("Failed to move file with error \(error).")
}
Form {
DocumentPreviewHeader($isHeaderVisible, url: url)
RuleFormSection(ruleFormModel, url: url)
}
.navigationTitle(ruleFormModel.name)
.conditionalTitle(!isHeaderVisible) {
DocumentPreviewButton(url: url, size: .navigationBarIcon)
}
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
Button("Move") {
do {
try ruleFormModel.move()
wizardModel.complete()
} catch {
// TODO: Present this error to the user.
print("Failed to move file with error \(error).")
}
}
}
}
}

}
Loading

0 comments on commit 5f8ec17

Please sign in to comment.