mirror of
https://github.com/ivanvorobei/SwiftUI.git
synced 2026-04-11 03:27:12 +02:00
Xcode 11 beta 6
This commit is contained in:
@@ -10,7 +10,7 @@ import Foundation
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
import Combine
|
import Combine
|
||||||
|
|
||||||
final class GameLogic : BindableObject {
|
final class GameLogic : ObservableObject {
|
||||||
|
|
||||||
enum Direction {
|
enum Direction {
|
||||||
case left
|
case left
|
||||||
@@ -21,7 +21,7 @@ final class GameLogic : BindableObject {
|
|||||||
|
|
||||||
typealias BlockMatrixType = BlockMatrix<IdentifiedBlock>
|
typealias BlockMatrixType = BlockMatrix<IdentifiedBlock>
|
||||||
|
|
||||||
let willChange = PassthroughSubject<GameLogic, Never>()
|
let objectWillChange = PassthroughSubject<GameLogic, Never>()
|
||||||
|
|
||||||
fileprivate var _blockMatrix: BlockMatrixType!
|
fileprivate var _blockMatrix: BlockMatrixType!
|
||||||
var blockMatrix: BlockMatrixType {
|
var blockMatrix: BlockMatrixType {
|
||||||
@@ -42,12 +42,12 @@ final class GameLogic : BindableObject {
|
|||||||
_blockMatrix = BlockMatrixType()
|
_blockMatrix = BlockMatrixType()
|
||||||
generateNewBlocks()
|
generateNewBlocks()
|
||||||
|
|
||||||
willChange.send(self)
|
objectWillChange.send(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
func move(_ direction: Direction) {
|
func move(_ direction: Direction) {
|
||||||
defer {
|
defer {
|
||||||
willChange.send(self)
|
objectWillChange.send(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
var moved = false
|
var moved = false
|
||||||
@@ -136,7 +136,7 @@ final class GameLogic : BindableObject {
|
|||||||
|
|
||||||
// Don't forget to sync data.
|
// Don't forget to sync data.
|
||||||
defer {
|
defer {
|
||||||
willChange.send(self)
|
objectWillChange.send(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Place the first block.
|
// Place the first block.
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ struct BlockGridView : View {
|
|||||||
y: CGFloat(block.index.1) * (65 + 12) + 32.5 + 12)
|
y: CGFloat(block.index.1) * (65 + 12) + 32.5 + 12)
|
||||||
.zIndex(self.zIndex(block.item))
|
.zIndex(self.zIndex(block.item))
|
||||||
.transition(.blockAppear(from: self.blockEnterEdge))
|
.transition(.blockAppear(from: self.blockEnterEdge))
|
||||||
.animation(block.item == nil ? nil : .spring(mass: 1, stiffness: 400, damping: 56, initialVelocity: 0))
|
// .animation(block.item == nil ? nil : .spring(mass: 1, stiffness: 400, damping: 56, initialVelocity: 0))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.frame(width: 320, height: 320, alignment: .center)
|
.frame(width: 320, height: 320, alignment: .center)
|
||||||
|
|||||||
@@ -8,18 +8,18 @@ A model object that stores app data.
|
|||||||
import Combine
|
import Combine
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
final class UserData: BindableObject {
|
final class UserData: ObservableObject {
|
||||||
let willChange = PassthroughSubject<UserData, Never>()
|
let objectWillChange = PassthroughSubject<UserData, Never>()
|
||||||
|
|
||||||
var showFavoritesOnly = false {
|
var showFavoritesOnly = false {
|
||||||
didSet {
|
didSet {
|
||||||
willChange.send(self)
|
objectWillChange.send(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var landmarks = landmarkData {
|
var landmarks = landmarkData {
|
||||||
didSet {
|
didSet {
|
||||||
willChange.send(self)
|
objectWillChange.send(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ struct Calculator: View {
|
|||||||
.foregroundColor(Color.blue)
|
.foregroundColor(Color.blue)
|
||||||
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity)
|
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity)
|
||||||
.background(Color(red: 234 / 255.0, green: 240 / 255.0, blue: 241 / 255.0))
|
.background(Color(red: 234 / 255.0, green: 240 / 255.0, blue: 241 / 255.0))
|
||||||
.tapAction {
|
.onTapGesture {
|
||||||
self.touchAction(item)
|
self.touchAction(item)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ struct SearchUserView: View {
|
|||||||
|
|
||||||
List(viewModel.users) { user in
|
List(viewModel.users) { user in
|
||||||
SearchUserRow(user: user)
|
SearchUserRow(user: user)
|
||||||
.tapAction { print(user) }
|
.onTapGesture { print(user) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.navigationBarTitle(Text("Users"))
|
.navigationBarTitle(Text("Users"))
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
import Combine
|
import Combine
|
||||||
|
|
||||||
final class SearchUserViewModel: BindableObject {
|
final class SearchUserViewModel: ObservableObject {
|
||||||
var willChange = PassthroughSubject<SearchUserViewModel, Never>()
|
var objectWillChange = PassthroughSubject<SearchUserViewModel, Never>()
|
||||||
|
|
||||||
private(set) var users = [User]() {
|
private(set) var users = [User]() {
|
||||||
didSet {
|
didSet {
|
||||||
willChange.send(self)
|
objectWillChange.send(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private(set) var userImages = [User: UIImage]() {
|
private(set) var userImages = [User: UIImage]() {
|
||||||
didSet {
|
didSet {
|
||||||
willChange.send(self)
|
objectWillChange.send(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,18 +8,18 @@ A model object that stores app data.
|
|||||||
import Combine
|
import Combine
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
final class UserData: BindableObject {
|
final class UserData: ObservableObject {
|
||||||
let willChange = PassthroughSubject<UserData, Never>()
|
let objectWillChange = PassthroughSubject<UserData, Never>()
|
||||||
|
|
||||||
var showFavoritesOnly = false {
|
var showFavoritesOnly = false {
|
||||||
didSet {
|
didSet {
|
||||||
willChange.send(self)
|
objectWillChange.send(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var landmarks = landmarkData {
|
var landmarks = landmarkData {
|
||||||
didSet {
|
didSet {
|
||||||
willChange.send(self)
|
objectWillChange.send(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ struct ConverterView : View {
|
|||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
let inset = EdgeInsets(top: -8, leading: -20, bottom: -7, trailing: 5)
|
let inset = EdgeInsets(top: -8, leading: -20, bottom: -7, trailing: 5)
|
||||||
let doubleValue: Double = Double(self.$baseAmount.value) ?? 1.0
|
let doubleValue: Double = Double(self.$baseAmount.wrappedValue) ?? 1.0
|
||||||
|
|
||||||
return ZStack(alignment: Alignment.bottomTrailing) {
|
return ZStack(alignment: Alignment.bottomTrailing) {
|
||||||
NavigationView {
|
NavigationView {
|
||||||
@@ -56,7 +56,7 @@ struct ConverterView : View {
|
|||||||
.background(
|
.background(
|
||||||
RoundedRectangle(cornerRadius: 5)
|
RoundedRectangle(cornerRadius: 5)
|
||||||
.fill(Color.clear)
|
.fill(Color.clear)
|
||||||
.border(Color(red: 0.7, green: 0.7, blue: 0.7), width: 1 / UIScreen.main.scale, cornerRadius: 5)
|
.background(RoundedRectangle(cornerRadius: 5).strokeBorder(Color(red: 0.7, green: 0.7, blue: 0.7), lineWidth: 1 / UIScreen.main.scale))
|
||||||
.padding(inset)
|
.padding(inset)
|
||||||
)
|
)
|
||||||
}.background(Color.blue).cornerRadius(5)
|
}.background(Color.blue).cornerRadius(5)
|
||||||
@@ -64,7 +64,7 @@ struct ConverterView : View {
|
|||||||
List {
|
List {
|
||||||
// TODO: should filter out BaseCurrency from list
|
// TODO: should filter out BaseCurrency from list
|
||||||
ForEach(userData.userCurrency) { currency in
|
ForEach(userData.userCurrency) { currency in
|
||||||
CurrencyItemView(currency: currency, baseAmount: doubleValue, isEditing: self.$isEditing).tapAction {
|
CurrencyItemView(currency: currency, baseAmount: doubleValue, isEditing: self.$isEditing).onTapGesture {
|
||||||
// Swap this and base
|
// Swap this and base
|
||||||
self.userData.baseCurrency = currency
|
self.userData.baseCurrency = currency
|
||||||
}
|
}
|
||||||
@@ -89,7 +89,7 @@ struct ConverterView : View {
|
|||||||
.background(
|
.background(
|
||||||
RoundedRectangle(cornerRadius: 23)
|
RoundedRectangle(cornerRadius: 23)
|
||||||
.fill(Color.blue)
|
.fill(Color.blue)
|
||||||
.border(Color(red: 0.7, green: 0.7, blue: 0.7), width: 1 / UIScreen.main.scale, cornerRadius: 23))
|
.background(RoundedRectangle(cornerRadius: 23).strokeBorder(Color(red: 0.7, green: 0.7, blue: 0.7), lineWidth: 1 / UIScreen.main.scale)))
|
||||||
.foregroundColor(.white).font(.largeTitle)
|
.foregroundColor(.white).font(.largeTitle)
|
||||||
}.padding()
|
}.padding()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ struct CurrencyItemView: View {
|
|||||||
HStack(alignment: .center){
|
HStack(alignment: .center){
|
||||||
Image(systemName: "minus.circle")
|
Image(systemName: "minus.circle")
|
||||||
.foregroundColor(.red)
|
.foregroundColor(.red)
|
||||||
.tapAction(count: 1) {
|
.onTapGesture(count: 1) {
|
||||||
self.delete()
|
self.delete()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -51,27 +51,27 @@ struct UserDefaultValue<Value: Codable> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final class UserData: BindableObject {
|
final class UserData: ObservableObject {
|
||||||
let willChange = PassthroughSubject<UserData, Never>()
|
let objectWillChange = PassthroughSubject<UserData, Never>()
|
||||||
|
|
||||||
@UserDefaultValue(key: "allCurrencies", defaultValue: defaultCurrencies)
|
@UserDefaultValue(key: "allCurrencies", defaultValue: defaultCurrencies)
|
||||||
var allCurrencies: [Currency] {
|
var allCurrencies: [Currency] {
|
||||||
didSet {
|
didSet {
|
||||||
willChange.send(self)
|
objectWillChange.send(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@UserDefaultValue(key: "baseCurrency", defaultValue: defaultCurrencies[0])
|
@UserDefaultValue(key: "baseCurrency", defaultValue: defaultCurrencies[0])
|
||||||
var baseCurrency: Currency {
|
var baseCurrency: Currency {
|
||||||
didSet {
|
didSet {
|
||||||
willChange.send(self)
|
objectWillChange.send(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@UserDefaultValue(key: "userCurrency", defaultValue: defaultCurrencies)
|
@UserDefaultValue(key: "userCurrency", defaultValue: defaultCurrencies)
|
||||||
var userCurrency: [Currency] {
|
var userCurrency: [Currency] {
|
||||||
didSet {
|
didSet {
|
||||||
willChange.send(self)
|
objectWillChange.send(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,18 +8,18 @@ A model object that stores app data.
|
|||||||
import Combine
|
import Combine
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
final class UserData: BindableObject {
|
final class UserData: ObservableObject {
|
||||||
let willChange = PassthroughSubject<UserData, Never>()
|
let objectWillChange = PassthroughSubject<UserData, Never>()
|
||||||
|
|
||||||
var showFavoritesOnly = false {
|
var showFavoritesOnly = false {
|
||||||
didSet {
|
didSet {
|
||||||
willChange.send(self)
|
objectWillChange.send(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var landmarks = landmarkData {
|
var landmarks = landmarkData {
|
||||||
didSet {
|
didSet {
|
||||||
willChange.send(self)
|
objectWillChange.send(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,14 +22,14 @@ struct TaskEditView: View {
|
|||||||
let inset = EdgeInsets(top: -8, leading: -10, bottom: -7, trailing: -10)
|
let inset = EdgeInsets(top: -8, leading: -10, bottom: -7, trailing: -10)
|
||||||
return VStack(alignment: .leading, spacing: 0) {
|
return VStack(alignment: .leading, spacing: 0) {
|
||||||
TextField(
|
TextField(
|
||||||
"Enter New Title...", text: self.draftTitle.binding,
|
"Enter New Title...", text: self.draftTitle.projectedValue,
|
||||||
onEditingChanged: { _ in self.updateTask() },
|
onEditingChanged: { _ in self.updateTask() },
|
||||||
onCommit: {}
|
onCommit: {}
|
||||||
)
|
)
|
||||||
.background(
|
.background(
|
||||||
RoundedRectangle(cornerRadius: 5)
|
RoundedRectangle(cornerRadius: 5)
|
||||||
.fill(Color.clear)
|
.fill(Color.clear)
|
||||||
.border(Color(red: 0.7, green: 0.7, blue: 0.7), width: 1 / UIScreen.main.scale, cornerRadius: 5)
|
.background(RoundedRectangle(cornerRadius: 5).strokeBorder(Color(red: 0.7, green: 0.7, blue: 0.7), lineWidth: 1 / UIScreen.main.scale))
|
||||||
.padding(inset)
|
.padding(inset)
|
||||||
)
|
)
|
||||||
.padding(EdgeInsets(
|
.padding(EdgeInsets(
|
||||||
@@ -46,6 +46,6 @@ struct TaskEditView: View {
|
|||||||
|
|
||||||
private func updateTask() {
|
private func updateTask() {
|
||||||
guard let index = self.userData.tasks.firstIndex(of: self.task) else { return }
|
guard let index = self.userData.tasks.firstIndex(of: self.task) else { return }
|
||||||
self.userData.tasks[index].title = self.draftTitle.value
|
self.userData.tasks[index].title = self.draftTitle.wrappedValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ struct TaskItemView: View {
|
|||||||
if self.isEditing {
|
if self.isEditing {
|
||||||
Image(systemName: "minus.circle")
|
Image(systemName: "minus.circle")
|
||||||
.foregroundColor(.red)
|
.foregroundColor(.red)
|
||||||
.tapAction(count: 1) {
|
.onTapGesture(count: 1) {
|
||||||
self.delete()
|
self.delete()
|
||||||
}
|
}
|
||||||
NavigationLink(destination: TaskEditView(task: task).environmentObject(self.userData)) {
|
NavigationLink(destination: TaskEditView(task: task).environmentObject(self.userData)) {
|
||||||
|
|||||||
@@ -14,13 +14,13 @@ private let defaultTasks: [Task] = [
|
|||||||
Task(title: "Watch WWDC19 Keynote 🎉", isDone: true),
|
Task(title: "Watch WWDC19 Keynote 🎉", isDone: true),
|
||||||
]
|
]
|
||||||
|
|
||||||
final class UserData: BindableObject {
|
final class UserData: ObservableObject {
|
||||||
let willChange = PassthroughSubject<UserData, Never>()
|
let objectWillChange = PassthroughSubject<UserData, Never>()
|
||||||
|
|
||||||
@UserDefaultValue(key: "Tasks", defaultValue: defaultTasks)
|
@UserDefaultValue(key: "Tasks", defaultValue: defaultTasks)
|
||||||
var tasks: [Task] {
|
var tasks: [Task] {
|
||||||
didSet {
|
didSet {
|
||||||
willChange.send(self)
|
objectWillChange.send(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
import Combine
|
import Combine
|
||||||
|
|
||||||
final class Store<State, Action>: BindableObject {
|
final class Store<State, Action>: ObservableObject {
|
||||||
typealias Reducer = (State, Action) -> State
|
typealias Reducer = (State, Action) -> State
|
||||||
|
|
||||||
let willChange = PassthroughSubject<State, Never>()
|
let objectWillChange = PassthroughSubject<State, Never>()
|
||||||
|
|
||||||
var state: State {
|
var state: State {
|
||||||
lock.lock()
|
lock.lock()
|
||||||
@@ -29,6 +29,6 @@ final class Store<State, Action>: BindableObject {
|
|||||||
|
|
||||||
lock.unlock()
|
lock.unlock()
|
||||||
|
|
||||||
willChange.send(newState)
|
objectWillChange.send(newState)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,4 +9,5 @@
|
|||||||
import Combine
|
import Combine
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
extension JSONDecoder: TopLevelDecoder {}
|
// now in Foundation
|
||||||
|
//extension JSONDecoder: TopLevelDecoder {}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import SwiftUI
|
|||||||
|
|
||||||
struct RepositoryListView : View {
|
struct RepositoryListView : View {
|
||||||
|
|
||||||
@ObjectBinding
|
@ObservedObject
|
||||||
private(set) var viewModel: RepositoryListViewModel
|
private(set) var viewModel: RepositoryListViewModel
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
@@ -24,15 +24,15 @@ struct RepositoryListView : View {
|
|||||||
onCommit: { self.viewModel.search() })
|
onCommit: { self.viewModel.search() })
|
||||||
.frame(height: 40)
|
.frame(height: 40)
|
||||||
.padding(EdgeInsets(top: 0, leading: 8, bottom: 0, trailing: 8))
|
.padding(EdgeInsets(top: 0, leading: 8, bottom: 0, trailing: 8))
|
||||||
.border(Color.gray, cornerRadius: 8)
|
|
||||||
.padding(EdgeInsets(top: 0, leading: 16, bottom: 0, trailing: 16))
|
.padding(EdgeInsets(top: 0, leading: 16, bottom: 0, trailing: 16))
|
||||||
|
.background(RoundedRectangle(cornerRadius: 8).strokeBorder(Color.gray, lineWidth: 2))
|
||||||
|
|
||||||
Button(action: { self.viewModel.search() }) {
|
Button(action: { self.viewModel.search() }) {
|
||||||
Text("Search")
|
Text("Search")
|
||||||
}
|
}
|
||||||
.frame(height: 40)
|
.frame(height: 40)
|
||||||
.padding(EdgeInsets(top: 0, leading: 8, bottom: 0, trailing: 8))
|
.padding(EdgeInsets(top: 0, leading: 8, bottom: 0, trailing: 8))
|
||||||
.border(Color.blue, cornerRadius: 8)
|
.background(RoundedRectangle(cornerRadius: 8).strokeBorder(Color.blue, lineWidth: 2))
|
||||||
.padding(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 16))
|
.padding(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 16))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,10 +10,10 @@ import Combine
|
|||||||
import Foundation
|
import Foundation
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
final class RepositoryListViewModel: BindableObject {
|
final class RepositoryListViewModel: ObservableObject {
|
||||||
typealias SearchRepositories = (String) -> AnyPublisher<Result<[Repository], ErrorResponse>, Never>
|
typealias SearchRepositories = (String) -> AnyPublisher<Result<[Repository], ErrorResponse>, Never>
|
||||||
|
|
||||||
let willChange: AnyPublisher<RepositoryListViewModel, Never>
|
let objectWillChange: AnyPublisher<RepositoryListViewModel, Never>
|
||||||
private let _didChange = PassthroughSubject<RepositoryListViewModel, Never>()
|
private let _didChange = PassthroughSubject<RepositoryListViewModel, Never>()
|
||||||
|
|
||||||
private let _searchWithQuery = PassthroughSubject<String, Never>()
|
private let _searchWithQuery = PassthroughSubject<String, Never>()
|
||||||
@@ -34,7 +34,7 @@ final class RepositoryListViewModel: BindableObject {
|
|||||||
init<S: Scheduler>(searchRepositories: @escaping SearchRepositories = RepositoryAPI.search,
|
init<S: Scheduler>(searchRepositories: @escaping SearchRepositories = RepositoryAPI.search,
|
||||||
mainScheduler: S) {
|
mainScheduler: S) {
|
||||||
|
|
||||||
self.willChange = _didChange.eraseToAnyPublisher()
|
self.objectWillChange = _didChange.eraseToAnyPublisher()
|
||||||
|
|
||||||
let response = _searchWithQuery
|
let response = _searchWithQuery
|
||||||
.filter { !$0.isEmpty }
|
.filter { !$0.isEmpty }
|
||||||
|
|||||||
@@ -8,18 +8,18 @@ A model object that stores app data.
|
|||||||
import Combine
|
import Combine
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
final class UserData: BindableObject {
|
final class UserData: ObservableObject {
|
||||||
let willChange = PassthroughSubject<UserData, Never>()
|
let objectWillChange = PassthroughSubject<UserData, Never>()
|
||||||
|
|
||||||
var showFavoritesOnly = false {
|
var showFavoritesOnly = false {
|
||||||
didSet {
|
didSet {
|
||||||
willChange.send(self)
|
objectWillChange.send(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var landmarks = landmarkData {
|
var landmarks = landmarkData {
|
||||||
didSet {
|
didSet {
|
||||||
willChange.send(self)
|
objectWillChange.send(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,11 +11,10 @@ struct HikeBadge: View {
|
|||||||
var name: String
|
var name: String
|
||||||
var body: some View {
|
var body: some View {
|
||||||
VStack(alignment: .center) {
|
VStack(alignment: .center) {
|
||||||
// crashes in Beta 5
|
Badge()
|
||||||
// Badge()
|
.frame(width: 300, height: 300)
|
||||||
// .frame(width: 300, height: 300)
|
.scaleEffect(1.0 / 3.0)
|
||||||
// .scaleEffect(1.0 / 3.0)
|
.frame(width: 100, height: 100)
|
||||||
// .frame(width: 100, height: 100)
|
|
||||||
Text(name)
|
Text(name)
|
||||||
.font(.caption)
|
.font(.caption)
|
||||||
.accessibility(label: Text("Badge for \(name)."))
|
.accessibility(label: Text("Badge for \(name)."))
|
||||||
|
|||||||
@@ -8,18 +8,18 @@ A model object that stores app data.
|
|||||||
import Combine
|
import Combine
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
final class UserData: BindableObject {
|
final class UserData: ObservableObject {
|
||||||
let willChange = PassthroughSubject<UserData, Never>()
|
let objectWillChange = PassthroughSubject<UserData, Never>()
|
||||||
|
|
||||||
var showFavoritesOnly = false {
|
var showFavoritesOnly = false {
|
||||||
didSet {
|
didSet {
|
||||||
willChange.send(self)
|
objectWillChange.send(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var landmarks = landmarkData {
|
var landmarks = landmarkData {
|
||||||
didSet {
|
didSet {
|
||||||
willChange.send(self)
|
objectWillChange.send(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,10 +15,10 @@ struct ProfileHost: View {
|
|||||||
var body: some View {
|
var body: some View {
|
||||||
VStack(alignment: .leading, spacing: 20) {
|
VStack(alignment: .leading, spacing: 20) {
|
||||||
HStack {
|
HStack {
|
||||||
if self.mode?.value == .active {
|
if self.mode?.wrappedValue == .active {
|
||||||
Button(action: {
|
Button(action: {
|
||||||
self.draftProfile = self.profile
|
self.draftProfile = self.profile
|
||||||
self.mode?.animation().value = .inactive
|
self.mode?.animation().wrappedValue = .inactive
|
||||||
}) {
|
}) {
|
||||||
Text("Done")
|
Text("Done")
|
||||||
}
|
}
|
||||||
@@ -28,7 +28,7 @@ struct ProfileHost: View {
|
|||||||
|
|
||||||
EditButton()
|
EditButton()
|
||||||
}
|
}
|
||||||
if self.mode?.value == .inactive {
|
if self.mode?.wrappedValue == .inactive {
|
||||||
ProfileSummary(profile: profile)
|
ProfileSummary(profile: profile)
|
||||||
} else {
|
} else {
|
||||||
ProfileEditor(profile: $draftProfile)
|
ProfileEditor(profile: $draftProfile)
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ struct CategoryItem: View {
|
|||||||
VStack{
|
VStack{
|
||||||
Color.white
|
Color.white
|
||||||
.frame(width:65,height:65)
|
.frame(width:65,height:65)
|
||||||
.border(Color(red: 218.0/255.0, green: 218.0/255.0, blue: 218.0/255.0),width: 3,cornerRadius: 15)
|
.background(RoundedRectangle(cornerRadius: 15).strokeBorder(Color(red: 218.0/255.0, green: 218.0/255.0, blue: 218.0/255.0), lineWidth: 3))
|
||||||
.cornerRadius(15)
|
.cornerRadius(15)
|
||||||
zone
|
zone
|
||||||
.image(forSize: 55)
|
.image(forSize: 55)
|
||||||
|
|||||||
@@ -10,8 +10,8 @@ import Foundation
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
import Combine
|
import Combine
|
||||||
|
|
||||||
final class AppState: BindableObject {
|
final class AppState: ObservableObject {
|
||||||
var willChange = PassthroughSubject<AppState, Never>()
|
var objectWillChange = PassthroughSubject<AppState, Never>()
|
||||||
|
|
||||||
var moviesState: MoviesState
|
var moviesState: MoviesState
|
||||||
|
|
||||||
@@ -22,7 +22,7 @@ final class AppState: BindableObject {
|
|||||||
func dispatch(action: Action) {
|
func dispatch(action: Action) {
|
||||||
moviesState = MoviesStateReducer().reduce(state: moviesState, action: action)
|
moviesState = MoviesStateReducer().reduce(state: moviesState, action: action)
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
self.willChange.send(self)
|
self.objectWillChange.send(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,8 +10,8 @@ import Foundation
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
import Combine
|
import Combine
|
||||||
|
|
||||||
final class AppState: BindableObject {
|
final class AppState: ObservableObject {
|
||||||
var willChange = PassthroughSubject<AppState, Never>()
|
var objectWillChange = PassthroughSubject<AppState, Never>()
|
||||||
|
|
||||||
var usersState: UsersState
|
var usersState: UsersState
|
||||||
|
|
||||||
@@ -21,7 +21,7 @@ final class AppState: BindableObject {
|
|||||||
|
|
||||||
func dispatch(action: Action) {
|
func dispatch(action: Action) {
|
||||||
usersState = UserStateReducer().reduce(state: usersState, action: action)
|
usersState = UserStateReducer().reduce(state: usersState, action: action)
|
||||||
willChange.send(self)
|
objectWillChange.send(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ struct TabbarView : View {
|
|||||||
@State var selectedIndex: Int = 0
|
@State var selectedIndex: Int = 0
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
TabbedView(selection: $selectedIndex) {
|
TabView(selection: $selectedIndex) {
|
||||||
UsersListView()
|
UsersListView()
|
||||||
.tabItem({ Text("Users") })
|
.tabItem({ Text("Users") })
|
||||||
MapView()
|
MapView()
|
||||||
|
|||||||
@@ -25,12 +25,12 @@
|
|||||||
VStack(alignment: .leading, spacing: 10) {
|
VStack(alignment: .leading, spacing: 10) {
|
||||||
Text("User name")
|
Text("User name")
|
||||||
TextField("New name", text: $newUserName)
|
TextField("New name", text: $newUserName)
|
||||||
.textFieldStyle(.roundedBorder)
|
.textFieldStyle(RoundedBorderTextFieldStyle())
|
||||||
Divider()
|
Divider()
|
||||||
Text("Username")
|
Text("Username")
|
||||||
TextField("New username", text: $newUserUsername)
|
TextField("New username", text: $newUserUsername)
|
||||||
.textFieldStyle(.roundedBorder)
|
.textFieldStyle(RoundedBorderTextFieldStyle())
|
||||||
}.padding(16)
|
}.padding(16)
|
||||||
Button(action: save) {
|
Button(action: save) {
|
||||||
Text("Save")
|
Text("Save")
|
||||||
.padding(8)
|
.padding(8)
|
||||||
@@ -42,7 +42,7 @@
|
|||||||
Text("Close")
|
Text("Close")
|
||||||
})
|
})
|
||||||
.navigationBarTitle(Text("Edit \(user.name)"), displayMode: .inline)
|
.navigationBarTitle(Text("Edit \(user.name)"), displayMode: .inline)
|
||||||
|
|
||||||
Badge(text: "Saved successfully", color: .green, show: $showSaved)
|
Badge(text: "Saved successfully", color: .green, show: $showSaved)
|
||||||
Badge(text: "Missing username or name", color: .red, show: $showError)
|
Badge(text: "Missing username or name", color: .red, show: $showError)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ struct UsersListView : View {
|
|||||||
.onMove(perform: move)
|
.onMove(perform: move)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.listStyle(.grouped)
|
.listStyle(GroupedListStyle())
|
||||||
.navigationBarTitle(Text("Users (\(state.usersState.users.count))"))
|
.navigationBarTitle(Text("Users (\(state.usersState.users.count))"))
|
||||||
.navigationBarItems(trailing: EditButton())
|
.navigationBarItems(trailing: EditButton())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
import Combine
|
import Combine
|
||||||
|
|
||||||
public final class Store<StateType>: BindableObject where StateType: StateMachine {
|
public final class Store<StateType>: ObservableObject where StateType: StateMachine {
|
||||||
|
|
||||||
private let initialState: StateType
|
private let initialState: StateType
|
||||||
private var subsequentStates: [StateType] = []
|
private var subsequentStates: [StateType] = []
|
||||||
|
|
||||||
public let willChange = PassthroughSubject<Void, Never>()
|
public let objectWillChange = PassthroughSubject<Void, Never>()
|
||||||
|
|
||||||
public init(state: StateType) {
|
public init(state: StateType) {
|
||||||
initialState = state
|
initialState = state
|
||||||
@@ -23,7 +23,7 @@ public final class Store<StateType>: BindableObject where StateType: StateMachin
|
|||||||
var currentStateIndex: Int = 0 {
|
var currentStateIndex: Int = 0 {
|
||||||
didSet {
|
didSet {
|
||||||
withAnimation {
|
withAnimation {
|
||||||
willChange.send(())
|
objectWillChange.send(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,9 +5,9 @@ struct TimeTravelBarView : View {
|
|||||||
@EnvironmentObject var store: Store<TodoState>
|
@EnvironmentObject var store: Store<TodoState>
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
let indexBinding = Binding<Double>(
|
let indexBinding = Binding(
|
||||||
getValue: { Double(self.store.currentStateIndex) },
|
get: { Double(self.store.currentStateIndex) },
|
||||||
setValue: { self.store.currentStateIndex = Int($0) })
|
set: { self.store.currentStateIndex = Int($0) })
|
||||||
|
|
||||||
return Slider(value: indexBinding, in: 0...Double(store.stateCount-1))
|
return Slider(value: indexBinding, in: 0...Double(store.stateCount-1))
|
||||||
.background(Color.white)
|
.background(Color.white)
|
||||||
|
|||||||
@@ -6,9 +6,9 @@ struct AddItemView: View {
|
|||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
|
|
||||||
let textBinding = Binding<String>(
|
let textBinding = Binding(
|
||||||
getValue: { self.store.state.partialItemName },
|
get: { self.store.state.partialItemName },
|
||||||
setValue: { self.store.dispatch(event: .changePartialItemName($0)) })
|
set: { self.store.dispatch(event: .changePartialItemName($0)) })
|
||||||
|
|
||||||
return VStack(spacing: 16) {
|
return VStack(spacing: 16) {
|
||||||
TextField("Title", text: textBinding)
|
TextField("Title", text: textBinding)
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ struct ModalDimmingView : View {
|
|||||||
.opacity(0.3)
|
.opacity(0.3)
|
||||||
.edgesIgnoringSafeArea([.bottom, .top])
|
.edgesIgnoringSafeArea([.bottom, .top])
|
||||||
.transition(.opacity)
|
.transition(.opacity)
|
||||||
.tapAction {
|
.onTapGesture {
|
||||||
self.store.dispatch(event: .cancelCreatingItem)
|
self.store.dispatch(event: .cancelCreatingItem)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,12 +9,12 @@
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
import Combine
|
import Combine
|
||||||
|
|
||||||
final class UserData: BindableObject {
|
final class UserData: ObservableObject {
|
||||||
let willChange = PassthroughSubject<UserData, Never>()
|
let objectWillChange = PassthroughSubject<UserData, Never>()
|
||||||
|
|
||||||
var notes = NoteData.shared.notes {
|
var notes = NoteData.shared.notes {
|
||||||
didSet {
|
didSet {
|
||||||
willChange.send(self)
|
objectWillChange.send(self)
|
||||||
NoteData.shared.notes = notes
|
NoteData.shared.notes = notes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ struct NoteDetail : View {
|
|||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
VStack {
|
VStack {
|
||||||
TextField("", text: self.text.binding,
|
TextField("", text: self.text.projectedValue,
|
||||||
onEditingChanged: { _ in self.updateNote()},
|
onEditingChanged: { _ in self.updateNote()},
|
||||||
onCommit: {})
|
onCommit: {})
|
||||||
Spacer()
|
Spacer()
|
||||||
@@ -35,7 +35,7 @@ struct NoteDetail : View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func updateNote() {
|
private func updateNote() {
|
||||||
self.userData.notes[noteIndex].text = self.text.value
|
self.userData.notes[noteIndex].text = self.text.wrappedValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -67,6 +67,6 @@ struct VideoListView : View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.listStyle(.grouped)
|
}.listStyle(GroupedListStyle())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,24 +8,24 @@
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
import Combine
|
import Combine
|
||||||
|
|
||||||
final class UserData: BindableObject {
|
final class UserData: ObservableObject {
|
||||||
let willChange = PassthroughSubject<UserData, Never>()
|
let objectWillChange = PassthroughSubject<UserData, Never>()
|
||||||
|
|
||||||
var showFavoriteOnly = false {
|
var showFavoriteOnly = false {
|
||||||
didSet {
|
didSet {
|
||||||
willChange.send(self)
|
objectWillChange.send(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var videos = videoList {
|
var videos = videoList {
|
||||||
didSet {
|
didSet {
|
||||||
willChange.send(self)
|
objectWillChange.send(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var currentVideo = videoList[0] {
|
var currentVideo = videoList[0] {
|
||||||
didSet {
|
didSet {
|
||||||
willChange.send(self)
|
objectWillChange.send(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,13 +32,13 @@ struct VideoRow : View {
|
|||||||
|
|
||||||
Image(systemName: video.isFavorite ? "star.fill" : "star")
|
Image(systemName: video.isFavorite ? "star.fill" : "star")
|
||||||
.foregroundColor(video.isFavorite ? Color.yellow : Color.gray)
|
.foregroundColor(video.isFavorite ? Color.yellow : Color.gray)
|
||||||
.tapAction {
|
.onTapGesture {
|
||||||
self.setFavorite(video: self.video)
|
self.setFavorite(video: self.video)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.padding([.top, .bottom], 10)
|
.padding([.top, .bottom], 10)
|
||||||
.tapAction {
|
.onTapGesture {
|
||||||
self.setCurrentVideo(video: self.video)
|
self.setCurrentVideo(video: self.video)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,11 +11,10 @@ struct HikeBadge: View {
|
|||||||
var name: String
|
var name: String
|
||||||
var body: some View {
|
var body: some View {
|
||||||
VStack(alignment: .center) {
|
VStack(alignment: .center) {
|
||||||
// crashes in Beta 5
|
Badge()
|
||||||
// Badge()
|
.frame(width: 300, height: 300)
|
||||||
// .frame(width: 300, height: 300)
|
.scaleEffect(1.0 / 3.0)
|
||||||
// .scaleEffect(1.0 / 3.0)
|
.frame(width: 100, height: 100)
|
||||||
// .frame(width: 100, height: 100)
|
|
||||||
Text(name)
|
Text(name)
|
||||||
.font(.caption)
|
.font(.caption)
|
||||||
.accessibility(label: Text("Badge for \(name)."))
|
.accessibility(label: Text("Badge for \(name)."))
|
||||||
|
|||||||
@@ -8,19 +8,19 @@ A model object that stores app data.
|
|||||||
import Combine
|
import Combine
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
final class UserData: BindableObject {
|
final class UserData: ObservableObject {
|
||||||
|
|
||||||
let willChange = PassthroughSubject<UserData, Never>()
|
let objectWillChange = PassthroughSubject<UserData, Never>()
|
||||||
|
|
||||||
var showFavoritesOnly = false {
|
var showFavoritesOnly = false {
|
||||||
didSet {
|
didSet {
|
||||||
willChange.send(self)
|
objectWillChange.send(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var landmarks = landmarkData {
|
var landmarks = landmarkData {
|
||||||
didSet {
|
didSet {
|
||||||
willChange.send(self)
|
objectWillChange.send(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,10 +15,10 @@ struct ProfileHost: View {
|
|||||||
var body: some View {
|
var body: some View {
|
||||||
VStack(alignment: .leading, spacing: 20) {
|
VStack(alignment: .leading, spacing: 20) {
|
||||||
HStack {
|
HStack {
|
||||||
if self.mode?.value == .active {
|
if self.mode?.wrappedValue == .active {
|
||||||
Button(action: {
|
Button(action: {
|
||||||
self.draftProfile = self.profile
|
self.draftProfile = self.profile
|
||||||
self.mode?.animation().value = .inactive
|
self.mode?.animation().wrappedValue = .inactive
|
||||||
}) {
|
}) {
|
||||||
Text("Done")
|
Text("Done")
|
||||||
}
|
}
|
||||||
@@ -28,7 +28,7 @@ struct ProfileHost: View {
|
|||||||
|
|
||||||
EditButton()
|
EditButton()
|
||||||
}
|
}
|
||||||
if self.mode?.value == .inactive {
|
if self.mode?.wrappedValue == .inactive {
|
||||||
ProfileSummary(profile: profile)
|
ProfileSummary(profile: profile)
|
||||||
} else {
|
} else {
|
||||||
ProfileEditor(profile: $draftProfile)
|
ProfileEditor(profile: $draftProfile)
|
||||||
|
|||||||
Reference in New Issue
Block a user