WIP - custom widget creator

This commit is contained in:
Trey t
2022-02-13 13:34:41 -06:00
parent adcdf636c3
commit 1e7199337f
13 changed files with 457 additions and 4 deletions

View File

@@ -0,0 +1,21 @@
{
"images" : [
{
"filename" : "bolt-solid.svg",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><!--! Font Awesome Pro 6.0.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path d="M240.5 224H352C365.3 224 377.3 232.3 381.1 244.7C386.6 257.2 383.1 271.3 373.1 280.1L117.1 504.1C105.8 513.9 89.27 514.7 77.19 505.9C65.1 497.1 60.7 481.1 66.59 467.4L143.5 288H31.1C18.67 288 6.733 279.7 2.044 267.3C-2.645 254.8 .8944 240.7 10.93 231.9L266.9 7.918C278.2-1.92 294.7-2.669 306.8 6.114C318.9 14.9 323.3 30.87 317.4 44.61L240.5 224z"/></svg>

After

Width:  |  Height:  |  Size: 593 B

View File

@@ -0,0 +1,21 @@
{
"images" : [
{
"filename" : "dollar-sign-solid.svg",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><!--! Font Awesome Pro 6.0.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path d="M160 0C177.7 0 192 14.33 192 32V67.68C193.6 67.89 195.1 68.12 196.7 68.35C207.3 69.93 238.9 75.02 251.9 78.31C268.1 82.65 279.4 100.1 275 117.2C270.7 134.3 253.3 144.7 236.1 140.4C226.8 137.1 198.5 133.3 187.3 131.7C155.2 126.9 127.7 129.3 108.8 136.5C90.52 143.5 82.93 153.4 80.92 164.5C78.98 175.2 80.45 181.3 82.21 185.1C84.1 189.1 87.79 193.6 95.14 198.5C111.4 209.2 136.2 216.4 168.4 225.1L171.2 225.9C199.6 233.6 234.4 243.1 260.2 260.2C274.3 269.6 287.6 282.3 295.8 299.9C304.1 317.7 305.9 337.7 302.1 358.1C295.1 397 268.1 422.4 236.4 435.6C222.8 441.2 207.8 444.8 192 446.6V480C192 497.7 177.7 512 160 512C142.3 512 128 497.7 128 480V445.1C127.6 445.1 127.1 444.1 126.7 444.9L126.5 444.9C102.2 441.1 62.07 430.6 35 418.6C18.85 411.4 11.58 392.5 18.76 376.3C25.94 360.2 44.85 352.9 60.1 360.1C81.9 369.4 116.3 378.5 136.2 381.6C168.2 386.4 194.5 383.6 212.3 376.4C229.2 369.5 236.9 359.5 239.1 347.5C241 336.8 239.6 330.7 237.8 326.9C235.9 322.9 232.2 318.4 224.9 313.5C208.6 302.8 183.8 295.6 151.6 286.9L148.8 286.1C120.4 278.4 85.58 268.9 59.76 251.8C45.65 242.4 32.43 229.7 24.22 212.1C15.89 194.3 14.08 174.3 17.95 153C25.03 114.1 53.05 89.29 85.96 76.73C98.98 71.76 113.1 68.49 128 66.73V32C128 14.33 142.3 0 160 0V0z"/></svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -0,0 +1,21 @@
{
"images" : [
{
"filename" : "fire-solid.svg",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Pro 6.0.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path d="M323.5 51.25C302.8 70.5 284 90.75 267.4 111.1C240.1 73.62 206.2 35.5 168 0C69.75 91.12 0 210 0 281.6C0 408.9 100.2 512 224 512s224-103.1 224-230.4C448 228.4 396 118.5 323.5 51.25zM304.1 391.9C282.4 407 255.8 416 226.9 416c-72.13 0-130.9-47.73-130.9-125.2c0-38.63 24.24-72.64 72.74-130.8c7 8 98.88 125.4 98.88 125.4l58.63-66.88c4.125 6.75 7.867 13.52 11.24 19.9C364.9 290.6 353.4 357.4 304.1 391.9z"/></svg>

After

Width:  |  Height:  |  Size: 645 B

View File

@@ -0,0 +1,37 @@
//
// CenterTiledImage.swift
// Feels (iOS)
//
// Created by Trey Tartt on 2/13/22.
//
import SwiftUI
struct CenterTiledImage: View {
let imageName: String
let imageSize: CGSize
var body: some View {
GeometryReader { geoReader in
let horizontalTilesNeeded = ceil(geoReader.size.width / imageSize.width / 2) * 2 + 1
let verticalTilesNeeded = ceil(geoReader.size.height / imageSize.height / 2) * 2 + 1
Image(imageName)
.resizable(resizingMode: .tile)
.frame(
width: horizontalTilesNeeded * imageSize.width,
height: verticalTilesNeeded * imageSize.height
)
.position(x: geoReader.size.width * 0.5, y: geoReader.size.height * 0.5)
}
}
init?(imageName: String) {
guard let imageSize = UIImage(named: imageName)?.size else {
return nil
}
self.imageName = imageName
self.imageSize = imageSize
}
}

View File

@@ -16,6 +16,8 @@ class UserDefaultsStore {
case mainViewTopHeaderIndex
case theme
case customIcon
case contentViewCurrentSelectedHeaderViewBackDays
case contentViewHeaderTag
case contentViewHeaderTagViewOneViewType

View File

@@ -269,7 +269,7 @@ struct ContentView: View {
settingsButtonView
if viewModel.hasNoData {
Spacer()
EmptyView(viewModel: viewModel)
EmptyContentView(viewModel: viewModel)
Spacer()
} else {
ZStack {

View File

@@ -0,0 +1,321 @@
//
// CreateIconView.swift
// Feels (iOS)
//
// Created by Trey Tartt on 2/13/22.
//
import SwiftUI
struct CustomIcon {
let leftEye: Image
let rightEye: Image
let mouth: Image
let background: AnyView?
let bgColor: Color
let innerColor: Color
}
enum BackGroundOptions: String, CaseIterable {
case horrible
case bad
case average
case good
case great
case random
static var selectable: [BackGroundOptions] {
return [.great, .good, .average, .bad, .horrible]
}
}
enum Eyes {
case left
case right
}
enum EyeOptions: String, CaseIterable {
case fire = "fire"
case bolt = "bolt2"
case dollar = "dollar"
static public var defaultOption: AnyView {
let image = Image(EyeOptions.fire.rawValue, bundle: .main)
.resizable()
.frame(width: 20, height: 20)
return AnyView(image)
}
}
enum MouthOptions: String, CaseIterable {
case moonFill = "moon.fill"
case flame = "flame"
case flameCircle = "flame.circle"
static public var defaultOption: MouthOptions {
return MouthOptions.flameCircle
}
}
struct CreateIconView: View {
@State private var bgColor = Color.red
@State private var innerColor = Color.green
@State private var bgPattern = [(AnyView, UUID)]()
@State private var leftEye: AnyView = EyeOptions.defaultOption
@State private var rightEye: AnyView = EyeOptions.defaultOption
@State private var mouth: Image = Image(systemName: MouthOptions.defaultOption.rawValue)
private var randomElements: [AnyView] = [
AnyView(Image(BackGroundOptions.selectable.randomElement()!.rawValue)
.resizable()
.frame(width: 20, height: 20)),
AnyView(Image(BackGroundOptions.selectable.randomElement()!.rawValue)
.resizable()
.frame(width: 20, height: 20)),
AnyView(Image(BackGroundOptions.selectable.randomElement()!.rawValue)
.resizable()
.frame(width: 20, height: 20)),
AnyView(Image(BackGroundOptions.selectable.randomElement()!.rawValue)
.resizable()
.frame(width: 20, height: 20))
]
let columns = [
GridItem(.fixed(20), spacing: 0),
GridItem(.fixed(20), spacing: 0),
GridItem(.fixed(20), spacing: 0),
GridItem(.fixed(20), spacing: 0),
GridItem(.fixed(20), spacing: 0),
GridItem(.fixed(20), spacing: 0),
GridItem(.fixed(20), spacing: 0),
GridItem(.fixed(20), spacing: 0),
GridItem(.fixed(20), spacing: 0),
GridItem(.fixed(20), spacing: 0),
GridItem(.fixed(20), spacing: 0),
GridItem(.fixed(20), spacing: 0)
]
func update(eye: Eyes, eyeOption: EyeOptions) {
let image = Image(eyeOption.rawValue, bundle: .main)
.resizable()
.frame(width: 20, height: 20)
switch eye {
case .left:
leftEye = AnyView(image)
case .right:
rightEye = AnyView(image)
}
}
func createRandom() {
bgColor = Color(
red: .random(in: 0...1),
green: .random(in: 0...1),
blue: .random(in: 0...1)
)
innerColor = Color(
red: .random(in: 0...1),
green: .random(in: 0...1),
blue: .random(in: 0...1)
)
update(eye: .left, eyeOption: EyeOptions.allCases.randomElement()!)
update(eye: .right, eyeOption: EyeOptions.allCases.randomElement()!)
update(mouthOption: MouthOptions.allCases.randomElement()!)
update(background: BackGroundOptions.allCases.randomElement()!)
}
func update(mouthOption: MouthOptions) {
mouth = Image(systemName: mouthOption.rawValue)
}
func update(background: BackGroundOptions) {
bgPattern.removeAll()
if background == .random {
for _ in 0...120 {
let image = Image(BackGroundOptions.selectable.randomElement()!.rawValue, bundle: .main)
let sizedImage = image
.resizable()
.frame(width: 20, height: 20)
bgPattern.append((AnyView(sizedImage), UUID()))
}
return
}
let image = Image(background.rawValue, bundle: .main)
let sizedImage = image
.resizable()
.frame(width: 20, height: 20)
for _ in 0...120 {
bgPattern.append((AnyView(sizedImage), UUID()))
}
}
var mixBG: some View {
VStack {
HStack {
randomElements[0]
randomElements[1]
}
HStack {
randomElements[2]
randomElements[3]
}
}
}
var iconView: some View {
ZStack {
LazyVGrid(columns: columns, spacing: 0) {
ForEach(bgPattern, id: \.self.1) {
$0.0
}
}
.frame(width: 200, height: 200)
.position(x: 100, y: 110)
Circle()
.strokeBorder(Color.black, lineWidth: 12)
.background(Circle().fill(innerColor))
.frame(width: 120, height: 120, alignment: .center)
VStack {
Spacer()
.frame(height: 70)
HStack {
Spacer()
.frame(width: 72)
leftEye
Spacer()
.frame(width: 24)
rightEye
Spacer()
}
Spacer()
.frame(height: 28)
mouth
Spacer()
}
}
.frame(width: 200, height: 200)
.background(
bgColor
)
.cornerRadius(10)
}
var body: some View {
VStack {
iconView
.padding()
Spacer()
VStack {
ColorPicker("Set the background color", selection: $bgColor)
.padding([.leading, .trailing])
ColorPicker("Set the inner color", selection: $innerColor)
.padding([.leading, .trailing])
}
HStack {
Spacer()
Menu("Left Eye") {
ForEach(EyeOptions.allCases, id: \.self) { option in
Button(action: {
update(eye: .left, eyeOption: option)
}, label: {
Label(option.rawValue, image: option.rawValue)
})
}
}
Spacer()
Menu("Right Eye") {
ForEach(EyeOptions.allCases, id: \.self) { option in
Button(action: {
update(eye: .right, eyeOption: option)
}, label: {
Label(option.rawValue, image: option.rawValue)
})
}
}
Spacer()
Menu("Mouth") {
ForEach(MouthOptions.allCases, id: \.self) { option in
Button(action: {
update(mouthOption: option)
}, label: {
Image(systemName: option.rawValue)
})
}
}
Spacer()
}
.padding(.top, 10)
VStack{
Text("Background")
HStack {
ForEach(BackGroundOptions.selectable, id: \.self) { bg in
Image(bg.rawValue, bundle: .main)
.resizable()
.frame(width: CGFloat(50), height: CGFloat(50), alignment: .center)
.onTapGesture {
update(background: bg)
}
}
mixBG
.onTapGesture {
update(background: .random)
}
}
}
.padding(.top, 10)
Button(action: {
createRandom()
}, label: {
Text("Random")
.font(.title)
.fontWeight(.bold)
.foregroundColor(Color(UIColor.white))
.frame(minWidth: 0, maxWidth: .infinity)
.background(.blue)
})
Button(action: {
// let newIcon = CustomIcon(leftEye: leftEye,
// rightEye: rightEye,
// mouth: mouth,
// background: bgPattern,
// bgColor: bgColor,
// innerColor: innerColor)
}, label: {
Text("Save")
.font(.title)
.fontWeight(.bold)
.foregroundColor(Color(UIColor.white))
.frame(minWidth: 0, maxWidth: .infinity)
.background(.green)
})
}
}
}
struct CreateIconView_Previews: PreviewProvider {
static var previews: some View {
CreateIconView()
}
}

View File

@@ -7,7 +7,7 @@
import SwiftUI
struct EmptyView: View {
struct EmptyContentView: View {
@AppStorage(UserDefaultsStore.Keys.theme.rawValue, store: GroupUserDefaults.groupDefaults) private var theme: Theme = .system
let viewModel: ContentModeViewModel
@@ -38,8 +38,8 @@ struct EmptyView: View {
}
}
struct EmptyView_Previews: PreviewProvider {
struct EmptyContentView_Previews: PreviewProvider {
static var previews: some View {
EmptyView(viewModel: ContentModeViewModel())
EmptyContentView(viewModel: ContentModeViewModel())
}
}

View File

@@ -18,6 +18,7 @@ struct SettingsView: View {
@State private var showSpecialThanks = false
@State private var showWhyBGMode = false
@State private var showCreateCustomWidget = false
@ObservedObject var syncMonitor = SyncMonitor.shared
@AppStorage(UserDefaultsStore.Keys.useCloudKit.rawValue, store: GroupUserDefaults.groupDefaults) private var useCloudKit = false
@@ -35,6 +36,7 @@ struct SettingsView: View {
canDelete
changeIcon
themePicker
createCustomWidget
showOnboardingButton
whyBackgroundMode
specialThanksCell
@@ -58,6 +60,9 @@ struct SettingsView: View {
showOnboarding = false
})
}
.sheet(isPresented: $showCreateCustomWidget) {
CreateIconView()
}
.background(
theme.currentTheme.bg
.edgesIgnoringSafeArea(.all)
@@ -283,6 +288,20 @@ struct SettingsView: View {
.fixedSize(horizontal: false, vertical: true)
.cornerRadius(10, corners: [.topLeft, .topRight, .bottomLeft, .bottomRight])
}
private var createCustomWidget: some View {
ZStack {
Color(theme.currentTheme.secondaryBGColor)
Button(action: {
showCreateCustomWidget = true
}, label: {
Text("Create Custom Widget")
})
.padding()
}
.fixedSize(horizontal: false, vertical: true)
.cornerRadius(10, corners: [.topLeft, .topRight, .bottomLeft, .bottomRight])
}
}
struct SettingsView_Previews: PreviewProvider {