Merge branch 'develop'
This commit is contained in:
@@ -69,6 +69,8 @@
|
||||
1C683FCC2792281400745862 /* Stats.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C683FC92792281400745862 /* Stats.swift */; };
|
||||
1C744F2C278CE15600953A57 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C744F2B278CE15600953A57 /* AppDelegate.swift */; };
|
||||
1C747CC9279F06EB00762CBD /* CloudKitSyncMonitor in Frameworks */ = {isa = PBXBuildFile; productRef = 1C747CC8279F06EB00762CBD /* CloudKitSyncMonitor */; };
|
||||
1C76E86E27C882A400ADEE1F /* SharingImageModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C76E86D27C882A400ADEE1F /* SharingImageModels.swift */; };
|
||||
1C76E86F27C882A400ADEE1F /* SharingImageModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C76E86D27C882A400ADEE1F /* SharingImageModels.swift */; };
|
||||
1CA037702799FFA600D26164 /* HomeViewViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CA0376F2799FFA600D26164 /* HomeViewViewModel.swift */; };
|
||||
1CA03773279A293D00D26164 /* OnboardingTime.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CA03772279A293D00D26164 /* OnboardingTime.swift */; };
|
||||
1CA03775279A294800D26164 /* OnboardingDay.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CA03774279A294800D26164 /* OnboardingDay.swift */; };
|
||||
@@ -204,6 +206,7 @@
|
||||
1C658D7627C0744D003231EE /* PersistenceUPDATE.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PersistenceUPDATE.swift; sourceTree = "<group>"; };
|
||||
1C683FC92792281400745862 /* Stats.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Stats.swift; sourceTree = "<group>"; };
|
||||
1C744F2B278CE15600953A57 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
1C76E86D27C882A400ADEE1F /* SharingImageModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SharingImageModels.swift; sourceTree = "<group>"; };
|
||||
1CA0376F2799FFA600D26164 /* HomeViewViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeViewViewModel.swift; sourceTree = "<group>"; };
|
||||
1CA03772279A293D00D26164 /* OnboardingTime.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingTime.swift; sourceTree = "<group>"; };
|
||||
1CA03774279A294800D26164 /* OnboardingDay.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingDay.swift; sourceTree = "<group>"; };
|
||||
@@ -569,6 +572,7 @@
|
||||
1C2162F627C16D11004353D1 /* MoodTintable.swift */,
|
||||
1C361F1327C03C8600E832FC /* OnboardingDataDataManager.swift */,
|
||||
1C04488627C1C81D00D22444 /* PersonalityPackable.swift */,
|
||||
1C76E86D27C882A400ADEE1F /* SharingImageModels.swift */,
|
||||
1C358FAC27ADD0C3002C83A6 /* Theme.swift */,
|
||||
1C5F4977279C945E0092F1B4 /* UserDefaultsStore.swift */,
|
||||
);
|
||||
@@ -786,6 +790,7 @@
|
||||
1C04488D27C2ADDB00D22444 /* IconViewModel.swift in Sources */,
|
||||
1C2162F227C156E6004353D1 /* CustomizeView.swift in Sources */,
|
||||
1C683FCA2792281400745862 /* Stats.swift in Sources */,
|
||||
1C76E86E27C882A400ADEE1F /* SharingImageModels.swift in Sources */,
|
||||
1CAD603E27A6ECCD00C520BD /* SwitchableView.swift in Sources */,
|
||||
1CD90B76278C8119001C4FEA /* LocalNotification.swift in Sources */,
|
||||
1C358FB627B0AE15002C83A6 /* AllMoodsTotalTemplate.swift in Sources */,
|
||||
@@ -881,6 +886,7 @@
|
||||
1C04488B27C2ABDE00D22444 /* IconView.swift in Sources */,
|
||||
1C04489A27C3F24F00D22444 /* Color+Codable.swift in Sources */,
|
||||
1C361F1127C03C3D00E832FC /* OnboardingTime.swift in Sources */,
|
||||
1C76E86F27C882A400ADEE1F /* SharingImageModels.swift in Sources */,
|
||||
1CEC967227B9C9FB00CC8688 /* CustomWidgetView.swift in Sources */,
|
||||
1C2162F827C16E3C004353D1 /* MoodTintable.swift in Sources */,
|
||||
1C4FF3BC27BEDF6600BE8F34 /* ShowBasedOnVoteLogics.swift in Sources */,
|
||||
|
||||
@@ -267,11 +267,9 @@ struct SmallGraphicWidgetView: View {
|
||||
IconView(iconViewModel: IconViewModel(backgroundImage: first.graphic,
|
||||
bgColor: first.color,
|
||||
bgOverlayColor: first.secondaryColor,
|
||||
centerImage: first.graphic),
|
||||
isPreview: true)
|
||||
centerImage: first.graphic))
|
||||
} else {
|
||||
IconView(iconViewModel: IconViewModel.great,
|
||||
isPreview: false)
|
||||
IconView(iconViewModel: IconViewModel.great)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -293,8 +291,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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,9 +21,13 @@ class AppDelegate: NSObject, UIApplicationDelegate {
|
||||
UNUserNotificationCenter.current().delegate = self
|
||||
|
||||
let theme = UserDefaultsStore.theme()
|
||||
UIPageControl.appearance().currentPageIndicatorTintColor = UIColor.label
|
||||
UIPageControl.appearance().currentPageIndicatorTintColor = UIColor(theme.currentTheme.labelColor)
|
||||
UIPageControl.appearance().pageIndicatorTintColor = UIColor.systemGray
|
||||
UITabBar.appearance().backgroundColor = UIColor(cgColor: theme.currentTheme.secondaryBGColor.cgColor ?? UIColor.secondarySystemBackground.cgColor)
|
||||
|
||||
let appearance = UITabBarAppearance()
|
||||
appearance.configureWithOpaqueBackground()
|
||||
UITabBar.appearance().standardAppearance = appearance
|
||||
UITabBar.appearance().scrollEdgeAppearance = appearance
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -75,9 +75,9 @@ final class EmojiMoodImages: MoodImagable {
|
||||
case .great:
|
||||
return Image(uiImage: "😀".textToImage()!)
|
||||
case .missing:
|
||||
return Image(uiImage: "x".textToImage()!)
|
||||
return Image(uiImage: "X".textToImage()!)
|
||||
case .placeholder:
|
||||
return Image(uiImage: "x".textToImage()!)
|
||||
return Image(uiImage: "X".textToImage()!)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -96,9 +96,9 @@ final class HandEmojiMoodImages: MoodImagable {
|
||||
case .great:
|
||||
return Image(uiImage: "🙏".textToImage()!)
|
||||
case .missing:
|
||||
return Image(uiImage: "x".textToImage()!)
|
||||
return Image(uiImage: "X".textToImage()!)
|
||||
case .placeholder:
|
||||
return Image(uiImage: "x".textToImage()!)
|
||||
return Image(uiImage: "X".textToImage()!)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,9 +79,9 @@ final class DefaultMoodTint: MoodTintable {
|
||||
case .great:
|
||||
return Color(hex: "31d158")
|
||||
case .missing:
|
||||
return Color(uiColor: UIColor.systemGray4)
|
||||
return Color(uiColor: UIColor.lightGray)
|
||||
case .placeholder:
|
||||
return Color(uiColor: UIColor.systemGray4)
|
||||
return Color(uiColor: UIColor.lightGray)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,9 +98,9 @@ final class DefaultMoodTint: MoodTintable {
|
||||
case .great:
|
||||
return Color(hex: "208939")
|
||||
case .missing:
|
||||
return Color(uiColor: UIColor.label)
|
||||
return Color(uiColor: UIColor.lightGray)
|
||||
case .placeholder:
|
||||
return Color(uiColor: UIColor.label)
|
||||
return Color(uiColor: UIColor.lightGray)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -189,19 +189,19 @@ final class MonoChromeTint: MoodTintable {
|
||||
static func color(forMood mood: Mood) -> Color {
|
||||
switch mood {
|
||||
case .horrible:
|
||||
return .black
|
||||
return Color(hex: "#000000")
|
||||
case .bad:
|
||||
return Color(uiColor: UIColor.systemGray)
|
||||
return Color(hex: "#47474a")
|
||||
case .average:
|
||||
return Color(uiColor: UIColor.systemGray)
|
||||
return Color(hex: "#7b7b81")
|
||||
case .good:
|
||||
return Color(uiColor: UIColor.systemGray2)
|
||||
return Color(hex: "#a3a3ab")
|
||||
case .great:
|
||||
return Color(uiColor: UIColor.systemGray3)
|
||||
return Color(hex: "#c2c1cb")
|
||||
case .missing:
|
||||
return Color(uiColor: UIColor.systemGray2)
|
||||
return Color(hex: "#ff0000")
|
||||
case .placeholder:
|
||||
return Color(uiColor: UIColor.systemGray4)
|
||||
return Color(hex: "#efeffb")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
59
Shared/Models/SharingImageModels.swift
Normal file
59
Shared/Models/SharingImageModels.swift
Normal file
@@ -0,0 +1,59 @@
|
||||
//
|
||||
// SharingImageModels.swift
|
||||
// Feels
|
||||
//
|
||||
// Created by Trey Tartt on 2/24/22.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import LinkPresentation
|
||||
|
||||
class StupidAssShareObservableObject: ObservableObject {
|
||||
@Published var fuckingWrappedShrable: UIImage? = nil
|
||||
@Published var showFuckingSheet = false
|
||||
}
|
||||
|
||||
class ShareActivityItemSource: NSObject, UIActivityItemSource {
|
||||
var shareText: String
|
||||
var shareImage: UIImage
|
||||
var linkMetaData = LPLinkMetadata()
|
||||
|
||||
init(shareText: String, shareImage: UIImage) {
|
||||
self.shareText = shareText
|
||||
self.shareImage = shareImage
|
||||
linkMetaData.title = shareText
|
||||
super.init()
|
||||
}
|
||||
|
||||
func activityViewControllerPlaceholderItem(_ activityViewController: UIActivityViewController) -> Any {
|
||||
return UIImage(named: "AppIcon") as Any
|
||||
}
|
||||
|
||||
func activityViewController(_ activityViewController: UIActivityViewController, itemForActivityType activityType: UIActivity.ActivityType?) -> Any? {
|
||||
return nil
|
||||
}
|
||||
|
||||
func activityViewControllerLinkMetadata(_ activityViewController: UIActivityViewController) -> LPLinkMetadata? {
|
||||
return linkMetaData
|
||||
}
|
||||
}
|
||||
|
||||
struct ShareSheet: UIViewControllerRepresentable {
|
||||
let photo: UIImage
|
||||
|
||||
func makeUIViewController(context: Context) -> UIActivityViewController {
|
||||
let text = "ifeel"
|
||||
let itemSource = ShareActivityItemSource(shareText: text, shareImage: photo)
|
||||
|
||||
let activityItems: [Any] = [photo, text, itemSource]
|
||||
|
||||
let controller = UIActivityViewController(
|
||||
activityItems: activityItems,
|
||||
applicationActivities: nil)
|
||||
|
||||
return controller
|
||||
}
|
||||
|
||||
func updateUIViewController(_ vc: UIActivityViewController, context: Context) {
|
||||
}
|
||||
}
|
||||
@@ -48,12 +48,17 @@ enum Theme: Int, CaseIterable {
|
||||
protocol Themeable {
|
||||
static var title: String { get }
|
||||
var secondaryBGColor: Color { get }
|
||||
var bgColor: Color { get }
|
||||
var bg: AnyView { get }
|
||||
var preview: AnyView { get }
|
||||
var labelColor: Color { get }
|
||||
}
|
||||
|
||||
struct IFeelTheme: Themeable {
|
||||
var bgColor: Color {
|
||||
return Color(uiColor: UIColor.systemBackground)
|
||||
}
|
||||
|
||||
var labelColor: Color {
|
||||
return Color(uiColor: UIColor.label)
|
||||
}
|
||||
@@ -63,7 +68,7 @@ struct IFeelTheme: Themeable {
|
||||
}
|
||||
|
||||
var secondaryBGColor: Color {
|
||||
return Color(uiColor: UIColor.systemBackground)
|
||||
return Color(uiColor: UIColor.secondarySystemBackground)
|
||||
}
|
||||
|
||||
var bg: AnyView {
|
||||
@@ -84,6 +89,10 @@ struct IFeelTheme: Themeable {
|
||||
}
|
||||
|
||||
struct SystemTheme: Themeable {
|
||||
var bgColor: Color {
|
||||
return Color(uiColor: UIColor.systemBackground)
|
||||
}
|
||||
|
||||
var labelColor: Color {
|
||||
return Color(uiColor: UIColor.label)
|
||||
}
|
||||
@@ -118,6 +127,10 @@ struct SystemTheme: Themeable {
|
||||
}
|
||||
|
||||
struct AlwaysDark: Themeable {
|
||||
var bgColor: Color {
|
||||
return Color(uiColor: UIColor.systemBackground.resolvedColor(with: .init(userInterfaceStyle: .dark)))
|
||||
}
|
||||
|
||||
var labelColor: Color {
|
||||
return .white
|
||||
}
|
||||
@@ -152,6 +165,10 @@ struct AlwaysDark: Themeable {
|
||||
}
|
||||
|
||||
struct AlwaysLight: Themeable {
|
||||
var bgColor: Color {
|
||||
return Color(uiColor: UIColor.systemBackground)
|
||||
}
|
||||
|
||||
var labelColor: Color {
|
||||
return .black
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
@@ -85,7 +85,7 @@ extension ChartDataBuildable {
|
||||
filledOutArray.append(view)
|
||||
} else {
|
||||
let thisDate = Calendar.current.date(bySetting: .day, value: day, of: month)!
|
||||
let view = ChartType(color: Mood.missing.color,
|
||||
let view = ChartType(color: Mood.placeholder.color,
|
||||
weekDay: Calendar.current.component(.weekday, from: thisDate),
|
||||
viewType: .square)
|
||||
filledOutArray.append(view)
|
||||
@@ -93,7 +93,7 @@ extension ChartDataBuildable {
|
||||
}
|
||||
|
||||
for _ in filledOutArray.count...32 {
|
||||
let view = ChartType(color: Mood.missing.color,
|
||||
let view = ChartType(color: Mood.placeholder.color,
|
||||
weekDay: 2,
|
||||
viewType: .cicle)
|
||||
filledOutArray.append(view)
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,28 +11,6 @@ struct IconView: View {
|
||||
@State public var iconViewModel: IconViewModel
|
||||
|
||||
private let facePercSize = 0.6
|
||||
public let isPreview: Bool
|
||||
|
||||
private var gridXOffset: CGFloat {
|
||||
if isPreview {
|
||||
return CGFloat(0)
|
||||
}
|
||||
return CGFloat(6)
|
||||
}
|
||||
|
||||
private var gridYOffset: CGFloat {
|
||||
if isPreview {
|
||||
return CGFloat(0)
|
||||
}
|
||||
return CGFloat(-8)
|
||||
}
|
||||
|
||||
private var entireFuckingViewOffset: CGFloat {
|
||||
if isPreview {
|
||||
return CGFloat(0)
|
||||
}
|
||||
return CGFloat(25)
|
||||
}
|
||||
|
||||
let columns = [
|
||||
GridItem(.flexible(minimum: 1, maximum: 100), spacing: 1),
|
||||
@@ -60,7 +38,7 @@ struct IconView: View {
|
||||
ForEach(iconViewModel.background, id: \.self.1) { (bgOption, uuid) in
|
||||
bgOption
|
||||
.resizable()
|
||||
.aspectRatio(1, contentMode: .fill)
|
||||
.aspectRatio(contentMode: .fill)
|
||||
.foregroundColor(iconViewModel.bgOverlayColor)
|
||||
}
|
||||
}
|
||||
@@ -76,7 +54,9 @@ struct IconView: View {
|
||||
.frame(width: geo.size.width*facePercSize,
|
||||
height: geo.size.height*facePercSize,
|
||||
alignment: .center)
|
||||
.position(x: geo.size.width/2, y: geo.size.height/2)
|
||||
.alignmentGuide(.top, computeValue: { _ in
|
||||
return geo.size.width/2
|
||||
})
|
||||
|
||||
iconViewModel.centerImage
|
||||
.resizable()
|
||||
@@ -85,11 +65,13 @@ struct IconView: View {
|
||||
height: geo.size.height*facePercSize,
|
||||
alignment: .center)
|
||||
.foregroundColor(iconViewModel.bgOverlayColor)
|
||||
.position(x: geo.size.width/2, y: geo.size.height/2)
|
||||
.alignmentGuide(.top, computeValue: { _ in
|
||||
return geo.size.width/2
|
||||
})
|
||||
|
||||
}
|
||||
.position(x: geo.size.width/2,
|
||||
y: geo.size.height/2 - entireFuckingViewOffset)
|
||||
y: geo.size.height/2)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -97,7 +79,7 @@ struct IconView: View {
|
||||
struct IconView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
Group {
|
||||
IconView(iconViewModel: IconViewModel.great, isPreview: false)
|
||||
IconView(iconViewModel: IconViewModel.great)
|
||||
.frame(width: 256, height: 256, alignment: .center)
|
||||
|
||||
// IconView(iconViewModel: IconViewModel.good, isPreview: true)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -54,7 +54,9 @@ struct CustomWidgetView: View {
|
||||
.frame(width: geo.size.width*facePercSize,
|
||||
height: geo.size.height*facePercSize,
|
||||
alignment: .center)
|
||||
.position(x: geo.size.width/2, y: geo.size.height/2)
|
||||
.alignmentGuide(.top, computeValue: { _ in
|
||||
return geo.size.width/2
|
||||
})
|
||||
|
||||
customWidgetModel.leftEye.image
|
||||
.resizable()
|
||||
@@ -63,7 +65,7 @@ struct CustomWidgetView: View {
|
||||
height: geo.size.height*0.12,
|
||||
alignment: .center)
|
||||
.position(x: geo.size.width*0.4,
|
||||
y: geo.size.height*0.4)
|
||||
y: geo.size.height*0.45)
|
||||
.foregroundColor(customWidgetModel.leftEyeColor)
|
||||
|
||||
customWidgetModel.rightEye.image
|
||||
@@ -73,7 +75,7 @@ struct CustomWidgetView: View {
|
||||
height: geo.size.height*0.12,
|
||||
alignment: .center)
|
||||
.position(x: geo.size.width*0.6,
|
||||
y: geo.size.height*0.4)
|
||||
y: geo.size.height*0.45)
|
||||
.foregroundColor(customWidgetModel.rightEyeColor)
|
||||
|
||||
customWidgetModel.mouth.image
|
||||
@@ -83,7 +85,7 @@ struct CustomWidgetView: View {
|
||||
height: geo.size.height*0.12,
|
||||
alignment: .center)
|
||||
.position(x: geo.size.width*0.5,
|
||||
y: geo.size.height*0.59)
|
||||
y: geo.size.height*0.65)
|
||||
.foregroundColor(customWidgetModel.mouthColor)
|
||||
}
|
||||
.position(x: geo.size.width/2,
|
||||
@@ -94,7 +96,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)
|
||||
|
||||
}
|
||||
|
||||
@@ -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,34 +59,40 @@ struct CustomizeView: View {
|
||||
theme.currentTheme.secondaryBGColor
|
||||
VStack {
|
||||
Text(String(localized: "settings_view_change_icon"))
|
||||
HStack {
|
||||
|
||||
Button(action: {
|
||||
UIApplication.shared.setAlternateIconName(nil)
|
||||
}, label: {
|
||||
Image("FeelsAppIcon", bundle: .main)
|
||||
.resizable()
|
||||
.frame(width: 50, height:50)
|
||||
.cornerRadius(10)
|
||||
})
|
||||
.padding()
|
||||
|
||||
ForEach(iconSets, id: \.self.0){ iconSet in
|
||||
.font(.body)
|
||||
.foregroundColor(theme.currentTheme.labelColor)
|
||||
.padding(.top)
|
||||
|
||||
ScrollView(.horizontal) {
|
||||
HStack {
|
||||
Button(action: {
|
||||
UIApplication.shared.setAlternateIconName(iconSet.1) { (error) in
|
||||
// FIXME: Handle error
|
||||
}
|
||||
UIApplication.shared.setAlternateIconName(nil)
|
||||
}, label: {
|
||||
Image(iconSet.0, bundle: .main)
|
||||
Image("FeelsAppIcon", bundle: .main)
|
||||
.resizable()
|
||||
.frame(width: 50, height:50)
|
||||
.cornerRadius(10)
|
||||
})
|
||||
.padding()
|
||||
|
||||
ForEach(iconSets, id: \.self.0){ iconSet in
|
||||
Button(action: {
|
||||
UIApplication.shared.setAlternateIconName(iconSet.1) { (error) in
|
||||
// FIXME: Handle error
|
||||
}
|
||||
}, label: {
|
||||
Image(iconSet.0, bundle: .main)
|
||||
.resizable()
|
||||
.frame(width: 50, height:50)
|
||||
.cornerRadius(10)
|
||||
})
|
||||
}
|
||||
}
|
||||
.padding()
|
||||
}
|
||||
.background(RoundedRectangle(cornerRadius: 10).fill().foregroundColor(theme.currentTheme.bgColor))
|
||||
.padding()
|
||||
.cornerRadius(10)
|
||||
}
|
||||
.padding()
|
||||
}
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
.cornerRadius(10, corners: [.topLeft, .topRight, .bottomLeft, .bottomRight])
|
||||
@@ -90,6 +103,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
|
||||
@@ -105,6 +121,13 @@ struct CustomizeView: View {
|
||||
Text(aTheme.title)
|
||||
}
|
||||
})
|
||||
.contentShape(Rectangle())
|
||||
.background(
|
||||
RoundedRectangle(cornerRadius: 10, style: .continuous)
|
||||
.fill(theme == aTheme ? theme.currentTheme.bgColor : .clear)
|
||||
.padding(-5)
|
||||
|
||||
)
|
||||
Spacer()
|
||||
}
|
||||
}
|
||||
@@ -119,12 +142,34 @@ struct CustomizeView: View {
|
||||
private var createCustomWidget: some View {
|
||||
ZStack {
|
||||
theme.currentTheme.secondaryBGColor
|
||||
Button(action: {
|
||||
showCreateCustomWidget = true
|
||||
}, label: {
|
||||
VStack {
|
||||
Text("Create Custom Widget")
|
||||
})
|
||||
.font(.body)
|
||||
.foregroundColor(theme.currentTheme.labelColor)
|
||||
.onTapGesture {
|
||||
selectedWidget.fuckingWrapped = CustomWidgetModel.randomWidget
|
||||
selectedWidget.showFuckingSheet = true
|
||||
}
|
||||
.padding(.top)
|
||||
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()
|
||||
}
|
||||
.background(RoundedRectangle(cornerRadius: 10).fill().foregroundColor(theme.currentTheme.bgColor))
|
||||
.padding()
|
||||
.cornerRadius(10)
|
||||
}
|
||||
}
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
.cornerRadius(10, corners: [.topLeft, .topRight, .bottomLeft, .bottomRight])
|
||||
@@ -135,25 +180,36 @@ struct CustomizeView: View {
|
||||
theme.currentTheme.secondaryBGColor
|
||||
VStack {
|
||||
ForEach(MoodImages.allCases, id: \.rawValue) { images in
|
||||
HStack {
|
||||
ForEach(Mood.allValues, id: \.self) { mood in
|
||||
images.icon(forMood: mood)
|
||||
.resizable()
|
||||
.aspectRatio(contentMode: .fit)
|
||||
.frame(width: 35, height: 35)
|
||||
.foregroundColor(
|
||||
moodTint.color(forMood: mood)
|
||||
)
|
||||
ZStack {
|
||||
VStack {
|
||||
HStack {
|
||||
ForEach(Mood.allValues, id: \.self) { mood in
|
||||
images.icon(forMood: mood)
|
||||
.resizable()
|
||||
.aspectRatio(contentMode: .fit)
|
||||
.frame(width: 35, height: 35)
|
||||
.foregroundColor(
|
||||
moodTint.color(forMood: mood)
|
||||
)
|
||||
}
|
||||
.frame(minWidth: 0, maxWidth: .infinity)
|
||||
}
|
||||
.contentShape(Rectangle())
|
||||
.background(
|
||||
RoundedRectangle(cornerRadius: 10, style: .continuous)
|
||||
.fill(imagePack == images ? theme.currentTheme.bgColor : .clear)
|
||||
.padding([.top, .bottom], -3)
|
||||
|
||||
)
|
||||
.onTapGesture {
|
||||
let impactMed = UIImpactFeedbackGenerator(style: .heavy)
|
||||
impactMed.impactOccurred()
|
||||
imagePack = images
|
||||
}
|
||||
if images.rawValue != (MoodImages.allCases.sorted(by: { $0.rawValue > $1.rawValue }).first?.rawValue) ?? 0 {
|
||||
Divider()
|
||||
}
|
||||
}
|
||||
.frame(minWidth: 0, maxWidth: .infinity)
|
||||
.onTapGesture {
|
||||
let impactMed = UIImpactFeedbackGenerator(style: .heavy)
|
||||
impactMed.impactOccurred()
|
||||
imagePack = images
|
||||
}
|
||||
}
|
||||
if images.rawValue != (MoodImages.allCases.sorted(by: { $0.rawValue > $1.rawValue }).first?.rawValue) ?? 0 {
|
||||
Divider()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -177,11 +233,18 @@ struct CustomizeView: View {
|
||||
)
|
||||
}
|
||||
.frame(minWidth: 0, maxWidth: .infinity)
|
||||
.onTapGesture {
|
||||
let impactMed = UIImpactFeedbackGenerator(style: .heavy)
|
||||
impactMed.impactOccurred()
|
||||
moodTint = tint
|
||||
}
|
||||
}
|
||||
.contentShape(Rectangle())
|
||||
.background(
|
||||
RoundedRectangle(cornerRadius: 10, style: .continuous)
|
||||
.fill(moodTint == tint ? theme.currentTheme.bgColor : .clear)
|
||||
.padding([.top, .bottom], -3)
|
||||
|
||||
)
|
||||
.onTapGesture {
|
||||
let impactMed = UIImpactFeedbackGenerator(style: .heavy)
|
||||
impactMed.impactOccurred()
|
||||
moodTint = tint
|
||||
}
|
||||
if tint.rawValue != (MoodTints.allCases.sorted(by: { $0.rawValue > $1.rawValue }).first?.rawValue) ?? 0 {
|
||||
Divider()
|
||||
@@ -201,8 +264,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)
|
||||
|
||||
|
||||
@@ -212,6 +274,13 @@ struct CustomizeView: View {
|
||||
}
|
||||
.frame(minWidth: 0, maxWidth: .infinity)
|
||||
.padding()
|
||||
.contentShape(Rectangle())
|
||||
.background(
|
||||
RoundedRectangle(cornerRadius: 10, style: .continuous)
|
||||
.fill(personalityPack == aPack ? theme.currentTheme.bgColor : .clear)
|
||||
.padding(5)
|
||||
|
||||
)
|
||||
.onTapGesture {
|
||||
let impactMed = UIImpactFeedbackGenerator(style: .heavy)
|
||||
impactMed.impactOccurred()
|
||||
|
||||
@@ -140,6 +140,7 @@ struct FilterView: View {
|
||||
.cornerRadius(10)
|
||||
.padding([.leading, .trailing])
|
||||
.foregroundColor(theme.currentTheme.labelColor)
|
||||
.accentColor(theme.currentTheme.labelColor)
|
||||
|
||||
ZStack {
|
||||
theme.currentTheme.secondaryBGColor
|
||||
@@ -156,6 +157,7 @@ struct FilterView: View {
|
||||
.cornerRadius(10)
|
||||
.padding([.leading, .trailing])
|
||||
.foregroundColor(theme.currentTheme.labelColor)
|
||||
.accentColor(theme.currentTheme.labelColor)
|
||||
|
||||
ZStack {
|
||||
theme.currentTheme.secondaryBGColor
|
||||
|
||||
@@ -318,6 +318,7 @@ extension HomeView {
|
||||
.foregroundColor(theme.currentTheme.labelColor)
|
||||
Text(" - ")
|
||||
.padding([.leading, .trailing], -10)
|
||||
.foregroundColor(theme.currentTheme.labelColor)
|
||||
Text(Random.dayFormat(fromDate:entry.forDate!))
|
||||
.font(.title3)
|
||||
.foregroundColor(theme.currentTheme.labelColor)
|
||||
|
||||
@@ -102,6 +102,7 @@ extension HomeViewTwo {
|
||||
Text("Vote")
|
||||
}
|
||||
Text("dis top")
|
||||
.foregroundColor(theme.currentTheme.secondaryBGColor)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -146,11 +147,12 @@ extension HomeViewTwo {
|
||||
LazyVGrid(columns: columns, spacing: 15) {
|
||||
ForEach(entries, id: \.self) { entry in
|
||||
Circle()
|
||||
.foregroundColor(moodTint.color(forMood: entry.mood))
|
||||
.foregroundColor(entry.mood == .placeholder ? .clear : moodTint.color(forMood: entry.mood))
|
||||
.frame(minHeight: 5, idealHeight: 20, maxHeight: 50, alignment: .center)
|
||||
}
|
||||
}
|
||||
}
|
||||
.contentShape(Rectangle())
|
||||
.onTapGesture{
|
||||
let deailView = MonthDetailView(monthInt: month,
|
||||
yearInt: year,
|
||||
|
||||
@@ -10,6 +10,10 @@ import SwiftUI
|
||||
struct MainTabView: View {
|
||||
@AppStorage(UserDefaultsStore.Keys.needsOnboarding.rawValue, store: GroupUserDefaults.groupDefaults) private var needsOnboarding = true
|
||||
|
||||
@AppStorage(UserDefaultsStore.Keys.theme.rawValue, store: GroupUserDefaults.groupDefaults) private var theme: Theme = .system
|
||||
|
||||
@AppStorage(UserDefaultsStore.Keys.moodTint.rawValue, store: GroupUserDefaults.groupDefaults) private var moodTint: MoodTints = .Default
|
||||
|
||||
let onboardingData = OnboardingDataDataManager.shared.savedOnboardingData
|
||||
|
||||
var body: some View {
|
||||
@@ -38,7 +42,9 @@ struct MainTabView: View {
|
||||
.tabItem {
|
||||
Label(String(localized: "content_view_tab_customize"), systemImage: "pencil")
|
||||
}
|
||||
}.sheet(isPresented: $needsOnboarding, onDismiss: {
|
||||
}
|
||||
.accentColor(moodTint.color(forMood: .average))
|
||||
.sheet(isPresented: $needsOnboarding, onDismiss: {
|
||||
|
||||
}, content: {
|
||||
OnboardingMain(onboardingData: onboardingData,
|
||||
@@ -47,6 +53,31 @@ struct MainTabView: View {
|
||||
OnboardingDataDataManager.shared.updateOnboardingData(onboardingData: onboardingData)
|
||||
})
|
||||
})
|
||||
.onAppear(perform: {
|
||||
switch theme {
|
||||
case .system:
|
||||
UIApplication.shared.windows.first?.overrideUserInterfaceStyle = .unspecified
|
||||
case .iFeel:
|
||||
UIApplication.shared.windows.first?.overrideUserInterfaceStyle = .unspecified
|
||||
case .dark:
|
||||
UIApplication.shared.windows.first?.overrideUserInterfaceStyle = .dark
|
||||
case .light:
|
||||
UIApplication.shared.windows.first?.overrideUserInterfaceStyle = .light
|
||||
}
|
||||
})
|
||||
.onChange(of: theme, perform: { value in
|
||||
print("changed to ", value)
|
||||
switch theme {
|
||||
case .system:
|
||||
UIApplication.shared.windows.first?.overrideUserInterfaceStyle = .unspecified
|
||||
case .iFeel:
|
||||
UIApplication.shared.windows.first?.overrideUserInterfaceStyle = .unspecified
|
||||
case .dark:
|
||||
UIApplication.shared.windows.first?.overrideUserInterfaceStyle = .dark
|
||||
case .light:
|
||||
UIApplication.shared.windows.first?.overrideUserInterfaceStyle = .light
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -84,11 +84,13 @@ struct SettingsView: View {
|
||||
}
|
||||
}, label: {
|
||||
Text(String(localized: "settings_view_special_thanks_to_title"))
|
||||
.foregroundColor(theme.currentTheme.labelColor)
|
||||
})
|
||||
.padding()
|
||||
|
||||
if showSpecialThanks {
|
||||
Text(String(localized: "settings_view_special_thanks_to_body"))
|
||||
.foregroundColor(theme.currentTheme.labelColor)
|
||||
.padding()
|
||||
}
|
||||
}
|
||||
@@ -105,6 +107,7 @@ struct SettingsView: View {
|
||||
editedDataClosure()
|
||||
}, label: {
|
||||
Text("Add test data")
|
||||
.foregroundColor(theme.currentTheme.labelColor)
|
||||
})
|
||||
.padding()
|
||||
}
|
||||
@@ -120,6 +123,7 @@ struct SettingsView: View {
|
||||
editedDataClosure()
|
||||
}, label: {
|
||||
Text("Clear DB")
|
||||
.foregroundColor(theme.currentTheme.labelColor)
|
||||
})
|
||||
.padding()
|
||||
}
|
||||
@@ -137,10 +141,12 @@ struct SettingsView: View {
|
||||
}
|
||||
}, label: {
|
||||
Text(String(localized: "settings_view_why_bg_mode_title"))
|
||||
.foregroundColor(theme.currentTheme.labelColor)
|
||||
})
|
||||
.padding()
|
||||
if showWhyBGMode {
|
||||
Text(String(localized: "settings_view_why_bg_mode_body"))
|
||||
.foregroundColor(theme.currentTheme.labelColor)
|
||||
.padding()
|
||||
}
|
||||
}
|
||||
@@ -160,6 +166,7 @@ struct SettingsView: View {
|
||||
showOnboarding.toggle()
|
||||
}, label: {
|
||||
Text(String(localized: "settings_view_show_onboarding"))
|
||||
.foregroundColor(theme.currentTheme.labelColor)
|
||||
})
|
||||
.padding()
|
||||
}
|
||||
@@ -171,13 +178,13 @@ struct SettingsView: View {
|
||||
ZStack {
|
||||
theme.currentTheme.secondaryBGColor
|
||||
VStack {
|
||||
Toggle(String(localized: "settings_use_cloudkit_title"),
|
||||
isOn: $useCloudKit)
|
||||
.onChange(of: useCloudKit) { value in
|
||||
PersistenceController.shared.switchContainer()
|
||||
}
|
||||
Toggle(isOn: $useCloudKit, label: {
|
||||
Text(String(localized: "settings_use_cloudkit_title"))
|
||||
.foregroundColor(theme.currentTheme.labelColor)
|
||||
})
|
||||
.padding()
|
||||
Text(String(localized: "settings_use_cloudkit_body"))
|
||||
.foregroundColor(theme.currentTheme.labelColor)
|
||||
}
|
||||
.padding(.bottom)
|
||||
}
|
||||
@@ -192,6 +199,7 @@ struct SettingsView: View {
|
||||
Image(systemName: syncMonitor.syncStateSummary.symbolName)
|
||||
.foregroundColor(syncMonitor.syncStateSummary.symbolColor)
|
||||
Text( syncMonitor.syncStateSummary.isBroken ? "cloudkit is broken" : "cloudkit is good")
|
||||
.foregroundColor(theme.currentTheme.labelColor)
|
||||
}
|
||||
.padding()
|
||||
}
|
||||
@@ -205,6 +213,7 @@ struct SettingsView: View {
|
||||
VStack {
|
||||
Toggle(String(localized: "settings_use_delete_enable"),
|
||||
isOn: $deleteEnabled)
|
||||
.foregroundColor(theme.currentTheme.labelColor)
|
||||
.padding()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,59 +29,64 @@ struct SharingListView: View {
|
||||
@Published var fuckingWrappedShrable: WrappedSharable? = nil
|
||||
@Published var showFuckingSheet = false
|
||||
}
|
||||
|
||||
|
||||
@StateObject private var selectedShare = StupidAssObservableObject()
|
||||
var sharebleItems = [WrappedSharable]()
|
||||
|
||||
let sharebleItems: [WrappedSharable] = [
|
||||
WrappedSharable(preview: AnyView(
|
||||
AllMoodsTotalTemplate(isPreview: true,
|
||||
startDate: PersistenceController.shared.earliestEntry?.forDate ?? Date(),
|
||||
endDate: Date(),
|
||||
fakeData: false)
|
||||
),destination: AnyView(
|
||||
AllMoodsTotalTemplate(isPreview: false,
|
||||
startDate: PersistenceController.shared.earliestEntry?.forDate ?? Date(),
|
||||
endDate: Date(),
|
||||
fakeData: false)
|
||||
),description: AllMoodsTotalTemplate.description),
|
||||
//////////////////////////////////////////////////////////
|
||||
WrappedSharable(preview: AnyView(
|
||||
CurrentStreakTemplate(isPreview: true,
|
||||
startDate: Calendar.current.date(byAdding: .day, value: -10, to: Date())!,
|
||||
endDate: Date(),
|
||||
fakeData: false)
|
||||
), destination: AnyView(
|
||||
CurrentStreakTemplate(isPreview: false,
|
||||
startDate: Calendar.current.date(byAdding: .day, value: -10, to: Date())!,
|
||||
endDate: Date(),
|
||||
fakeData: false)
|
||||
), description: CurrentStreakTemplate.description),
|
||||
//////////////////////////////////////////////////////////
|
||||
WrappedSharable(preview: AnyView(
|
||||
LongestStreakTemplate(isPreview: true,
|
||||
startDate: PersistenceController.shared.earliestEntry?.forDate ?? Date(),
|
||||
endDate: Date(),
|
||||
fakeData: false)
|
||||
), destination: AnyView(
|
||||
LongestStreakTemplate(isPreview: false,
|
||||
startDate: PersistenceController.shared.earliestEntry?.forDate ?? Date(),
|
||||
endDate: Date(),
|
||||
fakeData: false)
|
||||
), description: LongestStreakTemplate.description),
|
||||
//////////////////////////////////////////////////////////
|
||||
WrappedSharable(preview: AnyView(
|
||||
MonthTotalTemplate(isPreview: true,
|
||||
startDate: Date().startOfMonth,
|
||||
endDate: Date().endOfMonth,
|
||||
fakeData: false)
|
||||
), destination: AnyView(
|
||||
MonthTotalTemplate(isPreview: false,
|
||||
startDate: Date().startOfMonth,
|
||||
endDate: Date().endOfMonth,
|
||||
fakeData: false)
|
||||
), description: MonthTotalTemplate.description),
|
||||
//////////////////////////////////////////////////////////
|
||||
]
|
||||
init() {
|
||||
self.sharebleItems = [
|
||||
WrappedSharable(preview: AnyView(
|
||||
AllMoodsTotalTemplate(isPreview: true,
|
||||
startDate: PersistenceController.shared.earliestEntry?.forDate ?? Date(),
|
||||
endDate: Date(),
|
||||
fakeData: false)
|
||||
),destination: AnyView(
|
||||
AllMoodsTotalTemplate(isPreview: false,
|
||||
startDate: PersistenceController.shared.earliestEntry?.forDate ?? Date(),
|
||||
endDate: Date(),
|
||||
fakeData: false)
|
||||
),description: AllMoodsTotalTemplate.description),
|
||||
//////////////////////////////////////////////////////////
|
||||
WrappedSharable(preview: AnyView(
|
||||
CurrentStreakTemplate(isPreview: true,
|
||||
startDate: Calendar.current.date(byAdding: .day, value: -10, to: Date())!,
|
||||
endDate: Date(),
|
||||
fakeData: false)
|
||||
), destination: AnyView(
|
||||
CurrentStreakTemplate(isPreview: false,
|
||||
startDate: Calendar.current.date(byAdding: .day, value: -10, to: Date())!,
|
||||
endDate: Date(),
|
||||
fakeData: false)
|
||||
), description: CurrentStreakTemplate.description),
|
||||
//////////////////////////////////////////////////////////
|
||||
WrappedSharable(preview: AnyView(
|
||||
LongestStreakTemplate(isPreview: true,
|
||||
startDate: PersistenceController.shared.earliestEntry?.forDate ?? Date(),
|
||||
endDate: Date(),
|
||||
fakeData: false)
|
||||
), destination: AnyView(
|
||||
LongestStreakTemplate(isPreview: false,
|
||||
startDate: PersistenceController.shared.earliestEntry?.forDate ?? Date(),
|
||||
endDate: Date(),
|
||||
fakeData: false)
|
||||
), description: LongestStreakTemplate.description),
|
||||
//////////////////////////////////////////////////////////
|
||||
WrappedSharable(preview: AnyView(
|
||||
MonthTotalTemplate(isPreview: true,
|
||||
startDate: Date().startOfMonth,
|
||||
endDate: Date().endOfMonth,
|
||||
fakeData: false)
|
||||
), destination: AnyView(
|
||||
MonthTotalTemplate(isPreview: false,
|
||||
startDate: Date().startOfMonth,
|
||||
endDate: Date().endOfMonth,
|
||||
fakeData: false)
|
||||
), description: MonthTotalTemplate.description)
|
||||
//////////////////////////////////////////////////////////
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
|
||||
func didDismiss() {
|
||||
selectedShare.showFuckingSheet = false
|
||||
@@ -118,7 +123,7 @@ struct SharingListView: View {
|
||||
.frame(minWidth: 0, maxWidth: .infinity)
|
||||
.frame(height: 44)
|
||||
.background(
|
||||
Color(UIColor.secondarySystemBackground)
|
||||
theme.currentTheme.secondaryBGColor
|
||||
)
|
||||
.opacity(0.9)
|
||||
}
|
||||
@@ -132,15 +137,21 @@ struct SharingListView: View {
|
||||
})
|
||||
}
|
||||
|
||||
}.background(
|
||||
theme.currentTheme.bg
|
||||
.edgesIgnoringSafeArea(.all)
|
||||
)
|
||||
}
|
||||
}
|
||||
.background(
|
||||
theme.currentTheme.bg
|
||||
.edgesIgnoringSafeArea(.top)
|
||||
)
|
||||
.sheet(isPresented: $selectedShare.showFuckingSheet,
|
||||
onDismiss: didDismiss) {
|
||||
selectedShare.fuckingWrappedShrable?.destination
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func share(image: UIImage) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,14 +16,13 @@ struct AllMoodsTotalTemplate: View, SharingTemplate {
|
||||
var startDate: Date
|
||||
var endDate: Date
|
||||
var totalEntryCount: Int = 0
|
||||
|
||||
@State var showSharingTemplate = false
|
||||
|
||||
@Environment(\.presentationMode) var presentationMode
|
||||
@AppStorage(UserDefaultsStore.Keys.moodTint.rawValue, store: GroupUserDefaults.groupDefaults) private var moodTint: MoodTints = .Default
|
||||
@AppStorage(UserDefaultsStore.Keys.theme.rawValue, store: GroupUserDefaults.groupDefaults) private var theme: Theme = .system
|
||||
|
||||
@StateObject private var shareImage = StupidAssShareObservableObject()
|
||||
private var entries = [MoodMetrics]()
|
||||
|
||||
init(isPreview: Bool, startDate: Date, endDate: Date, fakeData: Bool) {
|
||||
self.isPreview = isPreview
|
||||
self.startDate = startDate
|
||||
@@ -53,7 +52,7 @@ struct AllMoodsTotalTemplate: View, SharingTemplate {
|
||||
}
|
||||
|
||||
var image: UIImage {
|
||||
let image = shareView.snapshot()
|
||||
let image = shareView.asImage(size: CGSize(width: 666, height: 1190))
|
||||
return image
|
||||
}
|
||||
|
||||
@@ -155,7 +154,10 @@ struct AllMoodsTotalTemplate: View, SharingTemplate {
|
||||
|
||||
HStack(alignment: .center) {
|
||||
Button(action: {
|
||||
showSharingTemplate = true
|
||||
let _image = self.image
|
||||
print(_image)
|
||||
self.shareImage.showFuckingSheet = true
|
||||
self.shareImage.fuckingWrappedShrable = _image
|
||||
}, label: {
|
||||
Text("Share")
|
||||
.font(.title)
|
||||
@@ -163,6 +165,11 @@ struct AllMoodsTotalTemplate: View, SharingTemplate {
|
||||
.foregroundColor(Color.white)
|
||||
.padding(.top, 20)
|
||||
})
|
||||
.sheet(isPresented: self.$shareImage.showFuckingSheet) {
|
||||
if let uiImage = self.shareImage.fuckingWrappedShrable {
|
||||
ShareSheet(photo: uiImage)
|
||||
}
|
||||
}
|
||||
.frame(maxWidth: .infinity, alignment: .center)
|
||||
.background(
|
||||
Color.green
|
||||
@@ -185,8 +192,6 @@ struct AllMoodsTotalTemplate: View, SharingTemplate {
|
||||
.padding(.leading, -5)
|
||||
}
|
||||
.padding([.leading, .trailing], -20)
|
||||
}.sheet(isPresented: $showSharingTemplate) {
|
||||
ActivityViewController(activityItems: [self.image])
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user