can have / save multiple custom widgets

This commit is contained in:
Trey t
2022-02-22 22:59:08 -06:00
parent 769c6335d9
commit 520119de85
6 changed files with 278 additions and 66 deletions

View File

@@ -293,8 +293,15 @@ struct SmallIconView: View {
var body: some View {
GeometryReader { geo in
CustomWidgetView(customWidgetModel: UserDefaultsStore.getCustomWidget())
.frame(width: geo.size.width, height: geo.size.height)
if let inUseWidget = UserDefaultsStore.getCustomWidgets().first(where: {
$0.inUse == true
}) {
CustomWidgetView(customWidgetModel: inUseWidget)
.frame(width: geo.size.width, height: geo.size.height)
} else {
CustomWidgetView(customWidgetModel: CustomWidgetModel.randomWidget)
.frame(width: geo.size.width, height: geo.size.height)
}
}
}
}

View File

@@ -82,21 +82,124 @@ class UserDefaultsStore {
}
}
static func getCustomWidget() -> CustomWidgetModel {
static func getCustomWidgets() -> [CustomWidgetModel] {
if let data = GroupUserDefaults.groupDefaults.object(forKey: UserDefaultsStore.Keys.customWidget.rawValue) as? Data,
let model = try? JSONDecoder().decode(CustomWidgetModel.self, from: data) {
let model = try? JSONDecoder().decode([CustomWidgetModel].self, from: data) {
return model
} else {
return CustomWidgetModel.defaultCustomWidget
GroupUserDefaults.groupDefaults.removeObject(forKey: UserDefaultsStore.Keys.customWidget.rawValue)
let widget = CustomWidgetModel.randomWidget
widget.isSaved = true
let widgets = [widget]
let data = try! JSONEncoder().encode(widgets)
GroupUserDefaults.groupDefaults.set(data, forKey: UserDefaultsStore.Keys.customWidget.rawValue)
if let data = GroupUserDefaults.groupDefaults.object(forKey: UserDefaultsStore.Keys.customWidget.rawValue) as? Data,
let models = try? JSONDecoder().decode([CustomWidgetModel].self, from: data) {
let sorted = models.sorted(by: {
$0.createdDate < $1.createdDate
})
return sorted
} else {
fatalError("error getting widgets")
}
}
}
@discardableResult
static func saveCustomWidget(widgetModel: CustomWidgetModel) -> CustomWidgetModel {
static func saveCustomWidget(widgetModel: CustomWidgetModel, inUse: Bool) -> [CustomWidgetModel] {
do {
let data = try JSONEncoder().encode(widgetModel)
var existingWidgets = getCustomWidgets()
if let exisitingWidget = existingWidgets.firstIndex(where: {
$0.uuid == widgetModel.uuid
}) {
existingWidgets.remove(at: exisitingWidget)
// give it differnet uuid so the view updates
widgetModel.uuid = UUID().uuidString
}
if inUse {
existingWidgets.forEach({
$0.inUse = false
})
widgetModel.inUse = true
}
existingWidgets.append(widgetModel)
existingWidgets.forEach({
$0.isSaved = true
})
let data = try JSONEncoder().encode(existingWidgets)
GroupUserDefaults.groupDefaults.set(data, forKey: UserDefaultsStore.Keys.customWidget.rawValue)
return UserDefaultsStore.getCustomWidget()
return UserDefaultsStore.getCustomWidgets()
} catch {
fatalError("error saving")
}
}
@discardableResult
static func deleteCustomWidget(withUUID uuid: String) -> [CustomWidgetModel] {
do {
var existingWidgets = getCustomWidgets()
if let exisitingWidget = existingWidgets.firstIndex(where: {
$0.uuid == uuid
}) {
existingWidgets.remove(at: exisitingWidget)
}
if existingWidgets.count == 0 {
let widget = CustomWidgetModel.randomWidget
widget.isSaved = true
widget.inUse = true
existingWidgets.append(widget)
}
if let _ = existingWidgets.first(where: {
$0.inUse == true
}) {} else {
if let first = existingWidgets.first {
first.inUse = true
}
}
let data = try JSONEncoder().encode(existingWidgets)
GroupUserDefaults.groupDefaults.set(data, forKey: UserDefaultsStore.Keys.customWidget.rawValue)
return UserDefaultsStore.getCustomWidgets()
} catch {
fatalError("error saving")
}
}
@discardableResult
static func makeWidgetCurrent(withUUID uuid: String) -> [CustomWidgetModel] {
do {
let existingWidgets = getCustomWidgets()
if let foundWidget = existingWidgets.first(where: {
$0.uuid == uuid
}) {
existingWidgets.forEach({
$0.inUse = false
})
foundWidget.inUse = true
} else {
if let first = existingWidgets.first {
first.inUse = true
}
}
existingWidgets.forEach({
$0.isSaved = true
})
let data = try JSONEncoder().encode(existingWidgets)
GroupUserDefaults.groupDefaults.set(data, forKey: UserDefaultsStore.Keys.customWidget.rawValue)
return UserDefaultsStore.getCustomWidgets()
} catch {
fatalError("error saving")
}

View File

@@ -9,8 +9,9 @@ import SwiftUI
struct CreateWidgetView: View {
@AppStorage(UserDefaultsStore.Keys.theme.rawValue, store: GroupUserDefaults.groupDefaults) private var theme: Theme = .system
@Environment(\.dismiss) var dismiss
@StateObject var customWidget = UserDefaultsStore.getCustomWidget()
@StateObject private var customWidget: CustomWidgetModel
static var iconViewBGs: [(CustomWidgetBackGroundOptions, UUID)] = {
var blah = [(CustomWidgetBackGroundOptions, UUID)]()
@@ -22,20 +23,26 @@ struct CreateWidgetView: View {
@State private var mouth: CustomWidgetMouthOptions = CustomWidgetMouthOptions.defaultOption
private var randomElements: [AnyView] = [
AnyView(Image(CustomWidgetBackGroundOptions.selectable.randomElement()!.rawValue)
.resizable()
.frame(width: 20, height: 20)),
AnyView(Image(CustomWidgetBackGroundOptions.selectable.randomElement()!.rawValue)
.resizable()
.frame(width: 20, height: 20)),
AnyView(Image(CustomWidgetBackGroundOptions.selectable.randomElement()!.rawValue)
.resizable()
.frame(width: 20, height: 20)),
AnyView(Image(CustomWidgetBackGroundOptions.selectable.randomElement()!.rawValue)
.resizable()
.frame(width: 20, height: 20))
]
private var randomElements: [AnyView]
init(customWidget: CustomWidgetModel, randomElements: [AnyView] = [AnyView]()) {
self.randomElements = [
AnyView(Image(CustomWidgetBackGroundOptions.selectable.randomElement()!.rawValue)
.resizable()
.frame(width: 20, height: 20)),
AnyView(Image(CustomWidgetBackGroundOptions.selectable.randomElement()!.rawValue)
.resizable()
.frame(width: 20, height: 20)),
AnyView(Image(CustomWidgetBackGroundOptions.selectable.randomElement()!.rawValue)
.resizable()
.frame(width: 20, height: 20)),
AnyView(Image(CustomWidgetBackGroundOptions.selectable.randomElement()!.rawValue)
.resizable()
.frame(width: 20, height: 20))
]
_customWidget = StateObject(wrappedValue: customWidget)
}
func update(eye: CustomWidgetEyes, eyeOption: CustomWidgetEyeOptions) {
switch eye {
@@ -90,7 +97,6 @@ struct CreateWidgetView: View {
var body: some View {
VStack(spacing: 0) {
widgetView
// .frame(width: 256, height: 256)
.cornerRadius(10)
.padding()
@@ -249,9 +255,10 @@ struct CreateWidgetView: View {
.background(.blue)
Button(action: {
UserDefaultsStore.saveCustomWidget(widgetModel: customWidget)
UserDefaultsStore.saveCustomWidget(widgetModel: customWidget, inUse: true)
let impactMed = UIImpactFeedbackGenerator(style: .heavy)
impactMed.impactOccurred()
dismiss()
}, label: {
Text("Save")
.font(.title)
@@ -261,6 +268,38 @@ struct CreateWidgetView: View {
})
.frame(minWidth: 0, maxWidth: .infinity)
.background(.green)
if customWidget.isSaved {
Button(action: {
UserDefaultsStore.deleteCustomWidget(withUUID: customWidget.uuid)
let impactMed = UIImpactFeedbackGenerator(style: .heavy)
impactMed.impactOccurred()
dismiss()
}, label: {
Text("Delete")
.font(.title)
.fontWeight(.bold)
.foregroundColor(Color(UIColor.white))
})
.frame(minWidth: 0, maxWidth: .infinity)
.background(.orange)
Button(action: {
UserDefaultsStore.makeWidgetCurrent(withUUID: customWidget.uuid)
let impactMed = UIImpactFeedbackGenerator(style: .heavy)
impactMed.impactOccurred()
dismiss()
}, label: {
Text("Use")
.font(.title)
.fontWeight(.bold)
.foregroundColor(Color(UIColor.white))
})
.frame(minWidth: 0, maxWidth: .infinity)
.background(.pink)
}
}
}
}
@@ -270,9 +309,9 @@ struct CreateWidgetView: View {
struct CreateIconView_Previews: PreviewProvider {
static var previews: some View {
Group {
CreateWidgetView()
CreateWidgetView(customWidget: CustomWidgetModel.randomWidget)
CreateWidgetView()
CreateWidgetView(customWidget: CustomWidgetModel.randomWidget)
.preferredColorScheme(.dark)
}
}

View File

@@ -7,21 +7,26 @@
import SwiftUI
class CustomWidgetModel: ObservableObject, Codable {
class CustomWidgetModel: ObservableObject, Codable, NSCopying {
static let numberOfBGItems = 109
static let defaultCustomWidget = CustomWidgetModel(leftEye: CustomWidgetEyeOptions.defaultOption,
rightEye: CustomWidgetEyeOptions.defaultOption,
mouth: CustomWidgetMouthOptions.defaultOption,
background: CustomWidgetBackGroundOptions.defaultOption,
bgColor: .red,
innerColor: .green,
bgOverlayColor: .orange,
rightEyeColor: .orange,
leftEyeColor: .yellow,
mouthColor: .green,
circleStrokeColor: .pink)
static var randomWidget: CustomWidgetModel {
return CustomWidgetModel(leftEye: CustomWidgetEyeOptions.defaultOption,
rightEye: CustomWidgetEyeOptions.defaultOption,
mouth: CustomWidgetMouthOptions.defaultOption,
background: CustomWidgetBackGroundOptions.defaultOption,
bgColor: Color.random(),
innerColor: Color.random(),
bgOverlayColor: Color.random(),
rightEyeColor: Color.random(),
leftEyeColor: Color.random(),
mouthColor: Color.random(),
circleStrokeColor: Color.random(),
inUse: true,
uuid: UUID().uuidString,
isSaved: false,
createdDate: Date())
}
init(leftEye: CustomWidgetEyeOptions,
rightEye: CustomWidgetEyeOptions,
@@ -33,8 +38,11 @@ class CustomWidgetModel: ObservableObject, Codable {
rightEyeColor: Color,
leftEyeColor: Color,
mouthColor: Color,
circleStrokeColor: Color
) {
circleStrokeColor: Color,
inUse: Bool,
uuid: String,
isSaved: Bool,
createdDate: Date) {
self.leftEye = leftEye
self.rightEye = rightEye
self.mouth = mouth
@@ -46,6 +54,10 @@ class CustomWidgetModel: ObservableObject, Codable {
self.leftEyeColor = leftEyeColor
self.mouthColor = mouthColor
self.circleStrokeColor = circleStrokeColor
self.inUse = inUse
self.uuid = uuid
self.isSaved = isSaved
self.createdDate = createdDate
}
@Published var leftEye: CustomWidgetEyeOptions
@@ -62,7 +74,11 @@ class CustomWidgetModel: ObservableObject, Codable {
@Published var mouthColor: Color
@Published var circleStrokeColor: Color
@Published var inUse: Bool
@Published var uuid: String
@Published var isSaved: Bool
@Published var createdDate: Date
public var backgroundImages : [(Image, String)] {
if background == .random {
var blah = [(Image, String)]()
@@ -81,7 +97,7 @@ class CustomWidgetModel: ObservableObject, Codable {
}
enum CodingKeys: CodingKey {
case leftEye, rightEye, mouth, background, bgColor, innerColor, bgOverlayColor, leftEyeColor, rightEyeColor, mouthColor, circleStrokeColor
case leftEye, rightEye, mouth, background, bgColor, innerColor, bgOverlayColor, leftEyeColor, rightEyeColor, mouthColor, circleStrokeColor, inUse, uuid, isSaved, createdDate
}
required init(from decoder: Decoder) throws {
@@ -98,6 +114,10 @@ class CustomWidgetModel: ObservableObject, Codable {
rightEyeColor = try container.decode(Color.self, forKey: .rightEyeColor)
mouthColor = try container.decode(Color.self, forKey: .mouthColor)
circleStrokeColor = try container.decode(Color.self, forKey: .circleStrokeColor)
inUse = try container.decode(Bool.self, forKey: .inUse)
uuid = try container.decode(String.self, forKey: .uuid)
isSaved = try container.decode(Bool.self, forKey: .isSaved)
createdDate = try container.decode(Date.self, forKey: .createdDate)
}
func encode(to encoder: Encoder) throws {
@@ -114,13 +134,29 @@ class CustomWidgetModel: ObservableObject, Codable {
try container.encode(rightEyeColor, forKey: .rightEyeColor)
try container.encode(mouthColor, forKey: .mouthColor)
try container.encode(circleStrokeColor, forKey: .circleStrokeColor)
try container.encode(inUse, forKey: .inUse)
try container.encode(uuid, forKey: .uuid)
try container.encode(isSaved, forKey: .isSaved)
try container.encode(createdDate, forKey: .createdDate)
}
func toData() -> Data {
if let data = try? JSONEncoder().encode(self) {
return data
}
return Data()
func copy(with zone: NSZone? = nil) -> Any {
let copy = CustomWidgetModel(leftEye: self.leftEye,
rightEye: self.rightEye,
mouth: self.mouth,
background: self.background,
bgColor: self.bgColor,
innerColor: self.innerColor,
bgOverlayColor: self.bgOverlayColor,
rightEyeColor: self.rightEyeColor,
leftEyeColor: self.leftEyeColor,
mouthColor: self.mouthColor,
circleStrokeColor: self.circleStrokeColor,
inUse: self.inUse,
uuid: self.uuid,
isSaved: self.isSaved,
createdDate: self.createdDate)
return copy
}
}

View File

@@ -94,7 +94,7 @@ struct CustomWidgetView: View {
struct WidgetView_Previews: PreviewProvider {
static var previews: some View {
CustomWidgetView(customWidgetModel: CustomWidgetModel.defaultCustomWidget)
CustomWidgetView(customWidgetModel: CustomWidgetModel.randomWidget)
.frame(width: 256, height: 256, alignment: .center)
}

View File

@@ -13,7 +13,12 @@ struct CustomizeView: View {
@AppStorage(UserDefaultsStore.Keys.moodTint.rawValue, store: GroupUserDefaults.groupDefaults) private var moodTint: MoodTints = .Default
@AppStorage(UserDefaultsStore.Keys.personalityPack.rawValue, store: GroupUserDefaults.groupDefaults) private var personalityPack: PersonalityPack = .Default
@State private var showCreateCustomWidget = false
class StupidAssCustomWidgetObservableObject: ObservableObject {
@Published var fuckingWrapped: CustomWidgetModel? = nil
@Published var showFuckingSheet = false
}
@StateObject private var selectedWidget = StupidAssCustomWidgetObservableObject()
let iconSets: [(String,String)] = [
("PurpleFeelsAppIcon", "PurpleAppIcon"),
@@ -38,8 +43,10 @@ struct CustomizeView: View {
}
}
.padding()
.sheet(isPresented: $showCreateCustomWidget) {
CreateWidgetView()
.sheet(isPresented: $selectedWidget.showFuckingSheet) {
if let fuckingWrapped = selectedWidget.fuckingWrapped {
CreateWidgetView(customWidget: fuckingWrapped)
}
}
.background(
theme.currentTheme.bg
@@ -52,8 +59,10 @@ struct CustomizeView: View {
theme.currentTheme.secondaryBGColor
VStack {
Text(String(localized: "settings_view_change_icon"))
.font(.body)
.foregroundColor(theme.currentTheme.labelColor)
HStack {
Button(action: {
UIApplication.shared.setAlternateIconName(nil)
}, label: {
@@ -62,8 +71,7 @@ struct CustomizeView: View {
.frame(width: 50, height:50)
.cornerRadius(10)
})
.padding()
ForEach(iconSets, id: \.self.0){ iconSet in
Button(action: {
UIApplication.shared.setAlternateIconName(iconSet.1) { (error) in
@@ -75,11 +83,10 @@ struct CustomizeView: View {
.frame(width: 50, height:50)
.cornerRadius(10)
})
.padding()
}
}
.padding()
}
.padding()
}
.fixedSize(horizontal: false, vertical: true)
.cornerRadius(10, corners: [.topLeft, .topRight, .bottomLeft, .bottomRight])
@@ -90,6 +97,9 @@ struct CustomizeView: View {
theme.currentTheme.secondaryBGColor
VStack {
Text(String(localized: "settings_background_title"))
.font(.body)
.foregroundColor(theme.currentTheme.labelColor)
HStack {
Spacer()
ForEach(Theme.allCases, id:\.rawValue) { aTheme in
@@ -119,12 +129,30 @@ struct CustomizeView: View {
private var createCustomWidget: some View {
ZStack {
theme.currentTheme.secondaryBGColor
Button(action: {
showCreateCustomWidget = true
}, label: {
VStack {
Text("Create Custom Widget")
})
.padding()
.font(.body)
.foregroundColor(theme.currentTheme.labelColor)
.onTapGesture {
selectedWidget.fuckingWrapped = CustomWidgetModel.randomWidget
selectedWidget.showFuckingSheet = true
}
.padding()
ScrollView(.horizontal) {
HStack {
ForEach(UserDefaultsStore.getCustomWidgets(), id: \.uuid) { widget in
CustomWidgetView(customWidgetModel: widget)
.frame(width: 50, height: 50)
.cornerRadius(10)
.onTapGesture {
selectedWidget.fuckingWrapped = widget.copy() as? CustomWidgetModel
selectedWidget.showFuckingSheet = true
}
}
}
.padding()
}
}
}
.fixedSize(horizontal: false, vertical: true)
.cornerRadius(10, corners: [.topLeft, .topRight, .bottomLeft, .bottomRight])
@@ -201,8 +229,7 @@ struct CustomizeView: View {
ForEach(PersonalityPack.allCases, id: \.self) { aPack in
VStack(spacing: 10) {
Text(String(aPack.title()))
.font(.title)
.fontWeight(.bold)
.font(.body)
.foregroundColor(theme.currentTheme.labelColor)