mirror of
https://github.com/ivanvorobei/SwiftUI.git
synced 2026-05-21 15:17:10 +02:00
@@ -38,14 +38,14 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
|||||||
gameLogic.newGame()
|
gameLogic.newGame()
|
||||||
}
|
}
|
||||||
|
|
||||||
override func buildCommands(with builder: UICommandBuilder) {
|
override func buildMenu(with builder: UIMenuBuilder) {
|
||||||
builder.remove(menu: .edit)
|
builder.remove(menu: .edit)
|
||||||
builder.remove(menu: .format)
|
builder.remove(menu: .format)
|
||||||
builder.remove(menu: .view)
|
builder.remove(menu: .view)
|
||||||
|
|
||||||
builder.replaceChildren(ofMenu: .file) { oldChildren in
|
builder.replaceChildren(ofMenu: .file) { oldChildren in
|
||||||
var newChildren = oldChildren
|
var newChildren = oldChildren
|
||||||
let newGameItem = UIMutableKeyCommand(input: "N",
|
let newGameItem = UIKeyCommand(input: "N",
|
||||||
modifierFlags: .command,
|
modifierFlags: .command,
|
||||||
action: #selector(newGame(_:)))
|
action: #selector(newGame(_:)))
|
||||||
newGameItem.title = "New Game"
|
newGameItem.title = "New Game"
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ final class GameLogic : BindableObject {
|
|||||||
|
|
||||||
typealias BlockMatrixType = BlockMatrix<IdentifiedBlock>
|
typealias BlockMatrixType = BlockMatrix<IdentifiedBlock>
|
||||||
|
|
||||||
let didChange = PassthroughSubject<GameLogic, Never>()
|
let willChange = 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()
|
||||||
|
|
||||||
didChange.send(self)
|
willChange.send(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
func move(_ direction: Direction) {
|
func move(_ direction: Direction) {
|
||||||
defer {
|
defer {
|
||||||
didChange.send(self)
|
willChange.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 {
|
||||||
didChange.send(self)
|
willChange.send(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Place the first block.
|
// Place the first block.
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ struct BlockView : View {
|
|||||||
|
|
||||||
Text(numberText)
|
Text(numberText)
|
||||||
.font(Font.system(size: fontSize).bold())
|
.font(Font.system(size: fontSize).bold())
|
||||||
.color(colorPair.1)
|
.foregroundColor(colorPair.1)
|
||||||
.id(numberText)
|
.id(numberText)
|
||||||
.transition(AnyTransition.scale(scale: 0.5, anchor: .center).combined(with: .opacity))
|
.transition(AnyTransition.scale(scale: 0.5, anchor: .center).combined(with: .opacity))
|
||||||
.animation(.fluidSpring())
|
.animation(.fluidSpring())
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ struct GameView : View {
|
|||||||
ZStack(alignment: layoutTraits.containerAlignment) {
|
ZStack(alignment: layoutTraits.containerAlignment) {
|
||||||
Text("2048")
|
Text("2048")
|
||||||
.font(Font.system(size: 48).weight(.black))
|
.font(Font.system(size: 48).weight(.black))
|
||||||
.color(Color(red:0.47, green:0.43, blue:0.40, opacity:1.00))
|
.foregroundColor(Color(red:0.47, green:0.43, blue:0.40, opacity:1.00))
|
||||||
.offset(layoutTraits.bannerOffset)
|
.offset(layoutTraits.bannerOffset)
|
||||||
|
|
||||||
ZStack(alignment: .top) {
|
ZStack(alignment: .top) {
|
||||||
|
|||||||
+1
-1
@@ -14,7 +14,7 @@ struct HikeView: View {
|
|||||||
var transition: AnyTransition {
|
var transition: AnyTransition {
|
||||||
let insertion = AnyTransition.move(edge: .trailing)
|
let insertion = AnyTransition.move(edge: .trailing)
|
||||||
.combined(with: .opacity)
|
.combined(with: .opacity)
|
||||||
let removal = AnyTransition.scale()
|
let removal = AnyTransition.scale(scale: 0.0)
|
||||||
.combined(with: .opacity)
|
.combined(with: .opacity)
|
||||||
return .asymmetric(insertion: insertion, removal: removal)
|
return .asymmetric(insertion: insertion, removal: removal)
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -35,7 +35,7 @@ struct LandmarkList: View {
|
|||||||
#if DEBUG
|
#if DEBUG
|
||||||
struct LandmarksList_Previews: PreviewProvider {
|
struct LandmarksList_Previews: PreviewProvider {
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
ForEach(["iPhone SE", "iPhone XS Max"].identified(by: \.self)) { deviceName in
|
ForEach(["iPhone SE", "iPhone XS Max"], id: \.self) { deviceName in
|
||||||
LandmarkList()
|
LandmarkList()
|
||||||
.previewDevice(PreviewDevice(rawValue: deviceName))
|
.previewDevice(PreviewDevice(rawValue: deviceName))
|
||||||
.previewDisplayName(deviceName)
|
.previewDisplayName(deviceName)
|
||||||
|
|||||||
+3
-3
@@ -9,17 +9,17 @@ import Combine
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
final class UserData: BindableObject {
|
final class UserData: BindableObject {
|
||||||
let didChange = PassthroughSubject<UserData, Never>()
|
let willChange = PassthroughSubject<UserData, Never>()
|
||||||
|
|
||||||
var showFavoritesOnly = false {
|
var showFavoritesOnly = false {
|
||||||
didSet {
|
didSet {
|
||||||
didChange.send(self)
|
willChange.send(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var landmarks = landmarkData {
|
var landmarks = landmarkData {
|
||||||
didSet {
|
didSet {
|
||||||
didChange.send(self)
|
willChange.send(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -23,7 +23,7 @@ struct LandmarkList: View {
|
|||||||
#if DEBUG
|
#if DEBUG
|
||||||
struct LandmarkList_Previews: PreviewProvider {
|
struct LandmarkList_Previews: PreviewProvider {
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
ForEach(["iPhone SE", "iPhone XS Max"].identified(by: \.self)) { deviceName in
|
ForEach(["iPhone SE", "iPhone XS Max"], id: \.self) { deviceName in
|
||||||
LandmarkList()
|
LandmarkList()
|
||||||
.previewDevice(PreviewDevice(rawValue: deviceName))
|
.previewDevice(PreviewDevice(rawValue: deviceName))
|
||||||
.previewDisplayName(deviceName)
|
.previewDisplayName(deviceName)
|
||||||
|
|||||||
@@ -33,13 +33,13 @@ struct Calculator: View {
|
|||||||
.padding(margin)
|
.padding(margin)
|
||||||
|
|
||||||
VStack(alignment: .center, spacing: margin) {
|
VStack(alignment: .center, spacing: margin) {
|
||||||
ForEach(data.identified(by: \.description)) { items in
|
ForEach(data, id: \.description) { items in
|
||||||
HStack(alignment: .center, spacing: margin) {
|
HStack(alignment: .center, spacing: margin) {
|
||||||
ForEach(items.identified(by: \.description)) { item in
|
ForEach(items, id: \.description) { item in
|
||||||
Text(item)
|
Text(item)
|
||||||
.font(.title)
|
.font(.title)
|
||||||
.bold()
|
.bold()
|
||||||
.color(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 {
|
.tapAction {
|
||||||
|
|||||||
+2
-2
@@ -40,7 +40,7 @@ extension Publisher {
|
|||||||
extension Publisher {
|
extension Publisher {
|
||||||
|
|
||||||
static func empty() -> AnyPublisher<Output, Failure> {
|
static func empty() -> AnyPublisher<Output, Failure> {
|
||||||
return Publishers.Empty()
|
return Empty()
|
||||||
.eraseToAnyPublisher()
|
.eraseToAnyPublisher()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,7 +51,7 @@ extension Publisher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static func fail(_ error: Failure) -> AnyPublisher<Output, Failure> {
|
static func fail(_ error: Failure) -> AnyPublisher<Output, Failure> {
|
||||||
return Publishers.Fail(error: error)
|
return Fail(error: error)
|
||||||
.eraseToAnyPublisher()
|
.eraseToAnyPublisher()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ struct SearchUserBar: View {
|
|||||||
TextField(
|
TextField(
|
||||||
$text,
|
$text,
|
||||||
placeholder: Text("Search User")
|
placeholder: Text("Search User")
|
||||||
.color(Color.gray)
|
.foregroundColor(Color.gray)
|
||||||
)
|
)
|
||||||
.padding([.leading, .trailing], 8)
|
.padding([.leading, .trailing], 8)
|
||||||
.frame(height: 32)
|
.frame(height: 32)
|
||||||
|
|||||||
+3
-3
@@ -2,17 +2,17 @@ import SwiftUI
|
|||||||
import Combine
|
import Combine
|
||||||
|
|
||||||
final class SearchUserViewModel: BindableObject {
|
final class SearchUserViewModel: BindableObject {
|
||||||
var didChange = PassthroughSubject<SearchUserViewModel, Never>()
|
var willChange = PassthroughSubject<SearchUserViewModel, Never>()
|
||||||
|
|
||||||
private(set) var users = [User]() {
|
private(set) var users = [User]() {
|
||||||
didSet {
|
didSet {
|
||||||
didChange.send(self)
|
willChange.send(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private(set) var userImages = [User: UIImage]() {
|
private(set) var userImages = [User: UIImage]() {
|
||||||
didSet {
|
didSet {
|
||||||
didChange.send(self)
|
willChange.send(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -20,7 +20,7 @@ struct CategoryRow: View {
|
|||||||
|
|
||||||
ScrollView(.horizontal) {
|
ScrollView(.horizontal) {
|
||||||
HStack(alignment: .top, spacing: 0) {
|
HStack(alignment: .top, spacing: 0) {
|
||||||
ForEach(self.items.identified(by: \.name)) { landmark in
|
ForEach(self.items, id: \.name) { landmark in
|
||||||
NavigationLink(
|
NavigationLink(
|
||||||
destination: LandmarkDetail(
|
destination: LandmarkDetail(
|
||||||
landmark: landmark
|
landmark: landmark
|
||||||
@@ -45,7 +45,7 @@ struct CategoryItem: View {
|
|||||||
.renderingMode(.original)
|
.renderingMode(.original)
|
||||||
.cornerRadius(5)
|
.cornerRadius(5)
|
||||||
Text(landmark.name)
|
Text(landmark.name)
|
||||||
.color(.primary)
|
.foregroundColor(.primary)
|
||||||
.font(.caption)
|
.font(.caption)
|
||||||
}
|
}
|
||||||
.padding(.leading, 15)
|
.padding(.leading, 15)
|
||||||
|
|||||||
+2
-2
@@ -23,13 +23,13 @@ struct HikeDetail: View {
|
|||||||
.frame(height: 200, alignment: .center)
|
.frame(height: 200, alignment: .center)
|
||||||
|
|
||||||
HStack(spacing: 25) {
|
HStack(spacing: 25) {
|
||||||
ForEach(buttons.identified(by: \.0)) { value in
|
ForEach(buttons, id: \.0) { value in
|
||||||
Button(action: {
|
Button(action: {
|
||||||
self.dataToShow = value.1
|
self.dataToShow = value.1
|
||||||
}) {
|
}) {
|
||||||
Text(verbatim: value.0)
|
Text(verbatim: value.0)
|
||||||
.font(.system(size: 15))
|
.font(.system(size: 15))
|
||||||
.color(value.1 == self.dataToShow
|
.foregroundColor(value.1 == self.dataToShow
|
||||||
? Color.gray
|
? Color.gray
|
||||||
: Color.accentColor)
|
: Color.accentColor)
|
||||||
.animation(nil)
|
.animation(nil)
|
||||||
|
|||||||
+1
-1
@@ -14,7 +14,7 @@ struct HikeView: View {
|
|||||||
var transition: AnyTransition {
|
var transition: AnyTransition {
|
||||||
let insertion = AnyTransition.move(edge: .trailing)
|
let insertion = AnyTransition.move(edge: .trailing)
|
||||||
.combined(with: .opacity)
|
.combined(with: .opacity)
|
||||||
let removal = AnyTransition.scale()
|
let removal = AnyTransition.scale(scale: 0.0)
|
||||||
.combined(with: .opacity)
|
.combined(with: .opacity)
|
||||||
return .asymmetric(insertion: insertion, removal: removal)
|
return .asymmetric(insertion: insertion, removal: removal)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ struct CategoryHome: View {
|
|||||||
.clipped()
|
.clipped()
|
||||||
.listRowInsets(EdgeInsets())
|
.listRowInsets(EdgeInsets())
|
||||||
|
|
||||||
ForEach(categories.keys.sorted().identified(by: \.self)) { key in
|
ForEach(categories.keys.sorted(), id: \.self) { key in
|
||||||
CategoryRow(categoryName: key, items: self.categories[key]!)
|
CategoryRow(categoryName: key, items: self.categories[key]!)
|
||||||
}
|
}
|
||||||
.listRowInsets(EdgeInsets())
|
.listRowInsets(EdgeInsets())
|
||||||
|
|||||||
+1
-1
@@ -35,7 +35,7 @@ struct LandmarkList: View {
|
|||||||
#if DEBUG
|
#if DEBUG
|
||||||
struct LandmarksList_Previews: PreviewProvider {
|
struct LandmarksList_Previews: PreviewProvider {
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
ForEach(["iPhone SE", "iPhone XS Max"].identified(by: \.self)) { deviceName in
|
ForEach(["iPhone SE", "iPhone XS Max"], id: \.self) { deviceName in
|
||||||
LandmarkList()
|
LandmarkList()
|
||||||
.previewDevice(PreviewDevice(rawValue: deviceName))
|
.previewDevice(PreviewDevice(rawValue: deviceName))
|
||||||
.previewDisplayName(deviceName)
|
.previewDisplayName(deviceName)
|
||||||
|
|||||||
+3
-3
@@ -9,17 +9,17 @@ import Combine
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
final class UserData: BindableObject {
|
final class UserData: BindableObject {
|
||||||
let didChange = PassthroughSubject<UserData, Never>()
|
let willChange = PassthroughSubject<UserData, Never>()
|
||||||
|
|
||||||
var showFavoritesOnly = false {
|
var showFavoritesOnly = false {
|
||||||
didSet {
|
didSet {
|
||||||
didChange.send(self)
|
willChange.send(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var landmarks = landmarkData {
|
var landmarks = landmarkData {
|
||||||
didSet {
|
didSet {
|
||||||
didChange.send(self)
|
willChange.send(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,14 +39,14 @@ struct ConverterView : View {
|
|||||||
return ZStack(alignment: Alignment.bottomTrailing) {
|
return ZStack(alignment: Alignment.bottomTrailing) {
|
||||||
NavigationView {
|
NavigationView {
|
||||||
VStack(alignment: .leading){
|
VStack(alignment: .leading){
|
||||||
Text("From:").bold().color(.gray)
|
Text("From:").bold().foregroundColor(.gray)
|
||||||
HStack{
|
HStack{
|
||||||
// Flag
|
// Flag
|
||||||
Text("\(userData.baseCurrency.flag)").padding(5)
|
Text("\(userData.baseCurrency.flag)").padding(5)
|
||||||
// Code and name
|
// Code and name
|
||||||
VStack(alignment: .leading){
|
VStack(alignment: .leading){
|
||||||
Text(userData.baseCurrency.code).color(.white)
|
Text(userData.baseCurrency.code).foregroundColor(.white)
|
||||||
Text(userData.baseCurrency.name).color(.white)
|
Text(userData.baseCurrency.name).foregroundColor(.white)
|
||||||
}
|
}
|
||||||
Spacer()
|
Spacer()
|
||||||
// Amount and conversion
|
// Amount and conversion
|
||||||
@@ -60,7 +60,7 @@ struct ConverterView : View {
|
|||||||
.padding(inset)
|
.padding(inset)
|
||||||
)
|
)
|
||||||
}.background(Color.blue).cornerRadius(5)
|
}.background(Color.blue).cornerRadius(5)
|
||||||
Text("To:").bold().color(.gray)
|
Text("To:").bold().foregroundColor(.gray)
|
||||||
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
|
||||||
@@ -79,7 +79,8 @@ struct ConverterView : View {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
HStack {
|
HStack {
|
||||||
Text("Last updated: \(self.lastUpdated)").color(.gray).bold()
|
Text("Last updated: \(self.lastUpdated)")
|
||||||
|
.foregroundColor(.gray).bold()
|
||||||
Spacer()
|
Spacer()
|
||||||
|
|
||||||
NavigationLink(destination: AddCurrencyView().environmentObject(self.userData)) {
|
NavigationLink(destination: AddCurrencyView().environmentObject(self.userData)) {
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ struct CurrencyItemView: View {
|
|||||||
Text(currency.flag).font(.title)
|
Text(currency.flag).font(.title)
|
||||||
VStack(alignment: .leading){
|
VStack(alignment: .leading){
|
||||||
Text(currency.code)
|
Text(currency.code)
|
||||||
Text(currency.name).color(.gray)
|
Text(currency.name).foregroundColor(.gray)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -61,14 +61,15 @@ struct CurrencyItemView: View {
|
|||||||
// Code and name
|
// Code and name
|
||||||
VStack(alignment: .leading){
|
VStack(alignment: .leading){
|
||||||
Text(currency.code).font(.headline)
|
Text(currency.code).font(.headline)
|
||||||
Text(currency.name).font(.footnote).color(.gray)
|
Text(currency.name).font(.footnote).foregroundColor(.gray)
|
||||||
}
|
}
|
||||||
Spacer()
|
Spacer()
|
||||||
// Amount and conversion
|
// Amount and conversion
|
||||||
VStack(alignment: .trailing){
|
VStack(alignment: .trailing){
|
||||||
Text("\(totalAmount)")
|
Text("\(totalAmount)")
|
||||||
// Would be 1 this currency = xxx base currency
|
// Would be 1 this currency = xxx base currency
|
||||||
Text("1 \(currency.code) = \(converstionRate) \(userData.baseCurrency.code)").color(.gray)
|
Text("1 \(currency.code) = \(converstionRate) \(userData.baseCurrency.code)")
|
||||||
|
.foregroundColor(.gray)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,13 +32,13 @@ private let defaultCurrencies: [Currency] = [
|
|||||||
Currency(name: "Canadian dollar", rate: 1.0, symbol: "CA", code: "CAD")
|
Currency(name: "Canadian dollar", rate: 1.0, symbol: "CA", code: "CAD")
|
||||||
]
|
]
|
||||||
|
|
||||||
@propertyDelegate
|
@propertyWrapper
|
||||||
struct UserDefaultValue<Value: Codable> {
|
struct UserDefaultValue<Value: Codable> {
|
||||||
|
|
||||||
let key: String
|
let key: String
|
||||||
let defaultValue: Value
|
let defaultValue: Value
|
||||||
|
|
||||||
var value: Value {
|
var wrappedValue: Value {
|
||||||
get {
|
get {
|
||||||
let data = UserDefaults.standard.data(forKey: key)
|
let data = UserDefaults.standard.data(forKey: key)
|
||||||
let value = data.flatMap { try? JSONDecoder().decode(Value.self, from: $0) }
|
let value = data.flatMap { try? JSONDecoder().decode(Value.self, from: $0) }
|
||||||
@@ -52,26 +52,26 @@ struct UserDefaultValue<Value: Codable> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final class UserData: BindableObject {
|
final class UserData: BindableObject {
|
||||||
let didChange = PassthroughSubject<UserData, Never>()
|
let willChange = PassthroughSubject<UserData, Never>()
|
||||||
|
|
||||||
@UserDefaultValue(key: "allCurrencies", defaultValue: defaultCurrencies)
|
@UserDefaultValue(key: "allCurrencies", defaultValue: defaultCurrencies)
|
||||||
var allCurrencies: [Currency] {
|
var allCurrencies: [Currency] {
|
||||||
didSet {
|
didSet {
|
||||||
didChange.send(self)
|
willChange.send(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@UserDefaultValue(key: "baseCurrency", defaultValue: defaultCurrencies[0])
|
@UserDefaultValue(key: "baseCurrency", defaultValue: defaultCurrencies[0])
|
||||||
var baseCurrency: Currency {
|
var baseCurrency: Currency {
|
||||||
didSet {
|
didSet {
|
||||||
didChange.send(self)
|
willChange.send(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@UserDefaultValue(key: "userCurrency", defaultValue: defaultCurrencies)
|
@UserDefaultValue(key: "userCurrency", defaultValue: defaultCurrencies)
|
||||||
var userCurrency: [Currency] {
|
var userCurrency: [Currency] {
|
||||||
didSet {
|
didSet {
|
||||||
didChange.send(self)
|
willChange.send(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -35,7 +35,7 @@ struct LandmarkList: View {
|
|||||||
#if DEBUG
|
#if DEBUG
|
||||||
struct LandmarksList_Previews: PreviewProvider {
|
struct LandmarksList_Previews: PreviewProvider {
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
ForEach(["iPhone SE", "iPhone XS Max"].identified(by: \.self)) { deviceName in
|
ForEach(["iPhone SE", "iPhone XS Max"], id: \.self) { deviceName in
|
||||||
LandmarkList()
|
LandmarkList()
|
||||||
.previewDevice(PreviewDevice(rawValue: deviceName))
|
.previewDevice(PreviewDevice(rawValue: deviceName))
|
||||||
.previewDisplayName(deviceName)
|
.previewDisplayName(deviceName)
|
||||||
|
|||||||
+3
-3
@@ -9,17 +9,17 @@ import Combine
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
final class UserData: BindableObject {
|
final class UserData: BindableObject {
|
||||||
let didChange = PassthroughSubject<UserData, Never>()
|
let willChange = PassthroughSubject<UserData, Never>()
|
||||||
|
|
||||||
var showFavoritesOnly = false {
|
var showFavoritesOnly = false {
|
||||||
didSet {
|
didSet {
|
||||||
didChange.send(self)
|
willChange.send(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var landmarks = landmarkData {
|
var landmarks = landmarkData {
|
||||||
didSet {
|
didSet {
|
||||||
didChange.send(self)
|
willChange.send(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,12 +15,12 @@ private let defaultTasks: [Task] = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
final class UserData: BindableObject {
|
final class UserData: BindableObject {
|
||||||
let didChange = PassthroughSubject<UserData, Never>()
|
let willChange = PassthroughSubject<UserData, Never>()
|
||||||
|
|
||||||
@UserDefaultValue(key: "Tasks", defaultValue: defaultTasks)
|
@UserDefaultValue(key: "Tasks", defaultValue: defaultTasks)
|
||||||
var tasks: [Task] {
|
var tasks: [Task] {
|
||||||
didSet {
|
didSet {
|
||||||
didChange.send(self)
|
willChange.send(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,13 +8,13 @@
|
|||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
@propertyDelegate
|
@propertyWrapper
|
||||||
struct UserDefaultValue<Value: Codable> {
|
struct UserDefaultValue<Value: Codable> {
|
||||||
|
|
||||||
let key: String
|
let key: String
|
||||||
let defaultValue: Value
|
let defaultValue: Value
|
||||||
|
|
||||||
var value: Value {
|
var wrappedValue: Value {
|
||||||
get {
|
get {
|
||||||
let data = UserDefaults.standard.data(forKey: key)
|
let data = UserDefaults.standard.data(forKey: key)
|
||||||
let value = data.flatMap { try? JSONDecoder().decode(Value.self, from: $0) }
|
let value = data.flatMap { try? JSONDecoder().decode(Value.self, from: $0) }
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import Combine
|
|||||||
final class Store<State, Action>: BindableObject {
|
final class Store<State, Action>: BindableObject {
|
||||||
typealias Reducer = (State, Action) -> State
|
typealias Reducer = (State, Action) -> State
|
||||||
|
|
||||||
let didChange = PassthroughSubject<State, Never>()
|
let willChange = 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()
|
||||||
|
|
||||||
didChange.send(newState)
|
willChange.send(newState)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -19,7 +19,7 @@ extension Publisher {
|
|||||||
extension Publisher {
|
extension Publisher {
|
||||||
|
|
||||||
static func empty() -> AnyPublisher<Output, Failure> {
|
static func empty() -> AnyPublisher<Output, Failure> {
|
||||||
return Publishers.Empty()
|
return Empty()
|
||||||
.eraseToAnyPublisher()
|
.eraseToAnyPublisher()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -30,7 +30,7 @@ extension Publisher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static func fail(_ error: Failure) -> AnyPublisher<Output, Failure> {
|
static func fail(_ error: Failure) -> AnyPublisher<Output, Failure> {
|
||||||
return Publishers.Fail(error: error)
|
return Fail(error: error)
|
||||||
.eraseToAnyPublisher()
|
.eraseToAnyPublisher()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -13,7 +13,7 @@ import SwiftUI
|
|||||||
final class RepositoryListViewModel: BindableObject {
|
final class RepositoryListViewModel: BindableObject {
|
||||||
typealias SearchRepositories = (String) -> AnyPublisher<Result<[Repository], ErrorResponse>, Never>
|
typealias SearchRepositories = (String) -> AnyPublisher<Result<[Repository], ErrorResponse>, Never>
|
||||||
|
|
||||||
let didChange: AnyPublisher<RepositoryListViewModel, Never>
|
let willChange: 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.didChange = _didChange.eraseToAnyPublisher()
|
self.willChange = _didChange.eraseToAnyPublisher()
|
||||||
|
|
||||||
let response = _searchWithQuery
|
let response = _searchWithQuery
|
||||||
.filter { !$0.isEmpty }
|
.filter { !$0.isEmpty }
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ struct LandmarkList: View {
|
|||||||
#if DEBUG
|
#if DEBUG
|
||||||
struct LandmarksList_Previews: PreviewProvider {
|
struct LandmarksList_Previews: PreviewProvider {
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
ForEach(["iPhone SE", "iPhone XS Max"].identified(by: \.self)) { deviceName in
|
ForEach(["iPhone SE", "iPhone XS Max"], id: \.self) { deviceName in
|
||||||
LandmarkList()
|
LandmarkList()
|
||||||
.previewDevice(PreviewDevice(rawValue: deviceName))
|
.previewDevice(PreviewDevice(rawValue: deviceName))
|
||||||
.previewDisplayName(deviceName)
|
.previewDisplayName(deviceName)
|
||||||
|
|||||||
+3
-3
@@ -9,17 +9,17 @@ import Combine
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
final class UserData: BindableObject {
|
final class UserData: BindableObject {
|
||||||
let didChange = PassthroughSubject<UserData, Never>()
|
let willChange = PassthroughSubject<UserData, Never>()
|
||||||
|
|
||||||
var showFavoritesOnly = false {
|
var showFavoritesOnly = false {
|
||||||
didSet {
|
didSet {
|
||||||
didChange.send(self)
|
willChange.send(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var landmarks = landmarkData {
|
var landmarks = landmarkData {
|
||||||
didSet {
|
didSet {
|
||||||
didChange.send(self)
|
willChange.send(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ struct ContentView : View {
|
|||||||
var body: some View {
|
var body: some View {
|
||||||
NavigationView {
|
NavigationView {
|
||||||
List {
|
List {
|
||||||
ForEach(instaPhotos.identified(by: \.id)) {
|
ForEach(instaPhotos, id: \.id) {
|
||||||
ImageCell(photo: $0)
|
ImageCell(photo: $0)
|
||||||
}
|
}
|
||||||
}.navigationBarTitle("WWDC").navigationBarItems(trailing: PresentationLink("Camera", destination: CameraView()))
|
}.navigationBarTitle("WWDC").navigationBarItems(trailing: PresentationLink("Camera", destination: CameraView()))
|
||||||
|
|||||||
+2
-2
@@ -20,7 +20,7 @@ struct CategoryRow: View {
|
|||||||
|
|
||||||
ScrollView(.horizontal) {
|
ScrollView(.horizontal) {
|
||||||
HStack(alignment: .top, spacing: 0) {
|
HStack(alignment: .top, spacing: 0) {
|
||||||
ForEach(self.items.identified(by: \.name)) { landmark in
|
ForEach(self.items, id: \.name) { landmark in
|
||||||
NavigationLink(
|
NavigationLink(
|
||||||
destination: LandmarkDetail(
|
destination: LandmarkDetail(
|
||||||
landmark: landmark
|
landmark: landmark
|
||||||
@@ -45,7 +45,7 @@ struct CategoryItem: View {
|
|||||||
.renderingMode(.original)
|
.renderingMode(.original)
|
||||||
.cornerRadius(5)
|
.cornerRadius(5)
|
||||||
Text(landmark.name)
|
Text(landmark.name)
|
||||||
.color(.primary)
|
.foregroundColor(.primary)
|
||||||
.font(.caption)
|
.font(.caption)
|
||||||
}
|
}
|
||||||
.padding(.leading, 15)
|
.padding(.leading, 15)
|
||||||
|
|||||||
@@ -23,13 +23,13 @@ struct HikeDetail: View {
|
|||||||
.frame(height: 200, alignment: .center)
|
.frame(height: 200, alignment: .center)
|
||||||
|
|
||||||
HStack(spacing: 25) {
|
HStack(spacing: 25) {
|
||||||
ForEach(buttons.identified(by: \.0)) { value in
|
ForEach(buttons, id: \.0) { value in
|
||||||
Button(action: {
|
Button(action: {
|
||||||
self.dataToShow = value.1
|
self.dataToShow = value.1
|
||||||
}) {
|
}) {
|
||||||
Text(verbatim: value.0)
|
Text(verbatim: value.0)
|
||||||
.font(.system(size: 15))
|
.font(.system(size: 15))
|
||||||
.color(value.1 == self.dataToShow
|
.foregroundColor(value.1 == self.dataToShow
|
||||||
? Color.gray
|
? Color.gray
|
||||||
: Color.accentColor)
|
: Color.accentColor)
|
||||||
.animation(nil)
|
.animation(nil)
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ struct HikeView: View {
|
|||||||
var transition: AnyTransition {
|
var transition: AnyTransition {
|
||||||
let insertion = AnyTransition.move(edge: .trailing)
|
let insertion = AnyTransition.move(edge: .trailing)
|
||||||
.combined(with: .opacity)
|
.combined(with: .opacity)
|
||||||
let removal = AnyTransition.scale()
|
let removal = AnyTransition.scale(scale: 0.0)
|
||||||
.combined(with: .opacity)
|
.combined(with: .opacity)
|
||||||
return .asymmetric(insertion: insertion, removal: removal)
|
return .asymmetric(insertion: insertion, removal: removal)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ struct CategoryHome: View {
|
|||||||
.clipped()
|
.clipped()
|
||||||
.listRowInsets(EdgeInsets())
|
.listRowInsets(EdgeInsets())
|
||||||
|
|
||||||
ForEach(categories.keys.sorted().identified(by: \.self)) { key in
|
ForEach(categories.keys.sorted(), id: \.self) { key in
|
||||||
CategoryRow(categoryName: key, items: self.categories[key]!)
|
CategoryRow(categoryName: key, items: self.categories[key]!)
|
||||||
}
|
}
|
||||||
.listRowInsets(EdgeInsets())
|
.listRowInsets(EdgeInsets())
|
||||||
|
|||||||
+1
-1
@@ -35,7 +35,7 @@ struct LandmarkList: View {
|
|||||||
#if DEBUG
|
#if DEBUG
|
||||||
struct LandmarksList_Previews: PreviewProvider {
|
struct LandmarksList_Previews: PreviewProvider {
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
ForEach(["iPhone SE", "iPhone XS Max"].identified(by: \.self)) { deviceName in
|
ForEach(["iPhone SE", "iPhone XS Max"], id: \.self) { deviceName in
|
||||||
LandmarkList()
|
LandmarkList()
|
||||||
.previewDevice(PreviewDevice(rawValue: deviceName))
|
.previewDevice(PreviewDevice(rawValue: deviceName))
|
||||||
.previewDisplayName(deviceName)
|
.previewDisplayName(deviceName)
|
||||||
|
|||||||
+3
-3
@@ -9,17 +9,17 @@ import Combine
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
final class UserData: BindableObject {
|
final class UserData: BindableObject {
|
||||||
let didChange = PassthroughSubject<UserData, Never>()
|
let willChange = PassthroughSubject<UserData, Never>()
|
||||||
|
|
||||||
var showFavoritesOnly = false {
|
var showFavoritesOnly = false {
|
||||||
didSet {
|
didSet {
|
||||||
didChange.send(self)
|
willChange.send(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var landmarks = landmarkData {
|
var landmarks = landmarkData {
|
||||||
didSet {
|
didSet {
|
||||||
didChange.send(self)
|
willChange.send(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ struct ActivityView : View {
|
|||||||
CircleImage(imgName: "subIcon")
|
CircleImage(imgName: "subIcon")
|
||||||
.padding(.leading, 10)
|
.padding(.leading, 10)
|
||||||
Text("发布动态...")
|
Text("发布动态...")
|
||||||
.color(Color.gray)
|
.foregroundColor(Color.gray)
|
||||||
Spacer()
|
Spacer()
|
||||||
}
|
}
|
||||||
HStack{
|
HStack{
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ struct ActivityCell : View {
|
|||||||
}
|
}
|
||||||
Text(timeStamp)
|
Text(timeStamp)
|
||||||
.font(Font.system(size: 12))
|
.font(Font.system(size: 12))
|
||||||
.color(Color.gray)
|
.foregroundColor(Color.gray)
|
||||||
.padding(.bottom, 2)
|
.padding(.bottom, 2)
|
||||||
|
|
||||||
Text(content)
|
Text(content)
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ struct CategoryRow: View {
|
|||||||
VStack(alignment: .leading) {
|
VStack(alignment: .leading) {
|
||||||
ScrollView(.horizontal) {
|
ScrollView(.horizontal) {
|
||||||
HStack(alignment: .top, spacing: 0) {
|
HStack(alignment: .top, spacing: 0) {
|
||||||
ForEach(self.items.identified(by: \.id)) { zone in
|
ForEach(self.items, id: \.id) { zone in
|
||||||
CategoryItem(zone: zone)
|
CategoryItem(zone: zone)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ struct ChatCell : View {
|
|||||||
.bold()
|
.bold()
|
||||||
.padding(.top, 4)
|
.padding(.top, 4)
|
||||||
Text(subTitle)
|
Text(subTitle)
|
||||||
.color(Color.gray)
|
.foregroundColor(Color.gray)
|
||||||
.padding(.bottom, 8)
|
.padding(.bottom, 8)
|
||||||
}
|
}
|
||||||
Spacer()
|
Spacer()
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ struct HomeCell : View {
|
|||||||
.bold()
|
.bold()
|
||||||
Text(timeStamp)
|
Text(timeStamp)
|
||||||
.font(Font.system(size: 12))
|
.font(Font.system(size: 12))
|
||||||
.color(Color.gray)
|
.foregroundColor(Color.gray)
|
||||||
.padding(.top, 8)
|
.padding(.top, 8)
|
||||||
}
|
}
|
||||||
Spacer()
|
Spacer()
|
||||||
@@ -57,7 +57,7 @@ struct HomeCell : View {
|
|||||||
.bold()
|
.bold()
|
||||||
Text("发布")
|
Text("发布")
|
||||||
.font(Font.system(size: 13))
|
.font(Font.system(size: 13))
|
||||||
.color(Color.gray)
|
.foregroundColor(Color.gray)
|
||||||
Spacer()
|
Spacer()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ struct ZoneCell : View {
|
|||||||
Image(imgName)
|
Image(imgName)
|
||||||
Text(title)
|
Text(title)
|
||||||
.font(Font.system(size: 10))
|
.font(Font.system(size: 10))
|
||||||
.color(Color.gray)
|
.foregroundColor(Color.gray)
|
||||||
.frame(alignment: .center)
|
.frame(alignment: .center)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ struct HomeView : View {
|
|||||||
.padding(EdgeInsets(top: 5, leading: 5, bottom: 5, trailing: 5))
|
.padding(EdgeInsets(top: 5, leading: 5, bottom: 5, trailing: 5))
|
||||||
Text("优衣库KAWS遭疯抢")
|
Text("优衣库KAWS遭疯抢")
|
||||||
.font(Font.system(size: 14))
|
.font(Font.system(size: 14))
|
||||||
.color(Color.gray)
|
.foregroundColor(Color.gray)
|
||||||
Spacer()
|
Spacer()
|
||||||
}
|
}
|
||||||
.background(
|
.background(
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import SwiftUI
|
|||||||
import Combine
|
import Combine
|
||||||
|
|
||||||
final class AppState: BindableObject {
|
final class AppState: BindableObject {
|
||||||
var didChange = PassthroughSubject<AppState, Never>()
|
var willChange = 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.didChange.send(self)
|
self.willChange.send(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import SwiftUI
|
|||||||
import Combine
|
import Combine
|
||||||
|
|
||||||
final class AppState: BindableObject {
|
final class AppState: BindableObject {
|
||||||
var didChange = PassthroughSubject<AppState, Never>()
|
var willChange = 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)
|
||||||
didChange.send(self)
|
willChange.send(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ struct Badge : View {
|
|||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
Text(text)
|
Text(text)
|
||||||
.color(.white)
|
.foregroundColor(.white)
|
||||||
.padding()
|
.padding()
|
||||||
.background(color)
|
.background(color)
|
||||||
.cornerRadius(8)
|
.cornerRadius(8)
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ struct UserRow : View {
|
|||||||
VStack {
|
VStack {
|
||||||
Text(user.name)
|
Text(user.name)
|
||||||
Text(user.username)
|
Text(user.username)
|
||||||
.color(.secondary)
|
.foregroundColor(.secondary)
|
||||||
.lineLimit(0)
|
.lineLimit(0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ public final class Store<StateType>: BindableObject where StateType: StateMachin
|
|||||||
private let initialState: StateType
|
private let initialState: StateType
|
||||||
private var subsequentStates: [StateType] = []
|
private var subsequentStates: [StateType] = []
|
||||||
|
|
||||||
public let didChange = PassthroughSubject<Void, Never>()
|
public let willChange = 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 {
|
||||||
didChange.send(())
|
willChange.send(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -17,7 +17,7 @@ struct ContentView: View {
|
|||||||
Text("Learning SwiftUI")
|
Text("Learning SwiftUI")
|
||||||
.font(.largeTitle)
|
.font(.largeTitle)
|
||||||
.fontWeight(.semibold)
|
.fontWeight(.semibold)
|
||||||
.color(.black)
|
.foregroundColor(.black)
|
||||||
.padding(4)
|
.padding(4)
|
||||||
.animation(.basic(duration: 0.3, curve: .easeOut))
|
.animation(.basic(duration: 0.3, curve: .easeOut))
|
||||||
|
|
||||||
@@ -33,7 +33,7 @@ struct ContentView: View {
|
|||||||
Text("A course focused on UI")
|
Text("A course focused on UI")
|
||||||
.font(.subheadline)
|
.font(.subheadline)
|
||||||
.fontWeight(.regular)
|
.fontWeight(.regular)
|
||||||
.color(.gray)
|
.foregroundColor(.gray)
|
||||||
.padding(4)
|
.padding(4)
|
||||||
.animation(.basic(duration: 0.4, curve: .easeIn))
|
.animation(.basic(duration: 0.4, curve: .easeIn))
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -19,19 +19,19 @@ struct ContentView : View {
|
|||||||
}) {
|
}) {
|
||||||
VStack() {
|
VStack() {
|
||||||
Text("Learn SwiftUI")
|
Text("Learn SwiftUI")
|
||||||
.color(.white)
|
.foregroundColor(.white)
|
||||||
.fontWeight(.bold)
|
.fontWeight(.bold)
|
||||||
.font(.largeTitle)
|
.font(.largeTitle)
|
||||||
.padding(.top, show ? 100 : 20)
|
.padding(.top, show ? 100 : 20)
|
||||||
|
|
||||||
Text("A course on UI and animations")
|
Text("A course on UI and animations")
|
||||||
.color(Color(hue: 0.567, saturation: 0.158, brightness: 0.943))
|
.foregroundColor(Color(hue: 0.567, saturation: 0.158, brightness: 0.943))
|
||||||
.lineLimit(-1)
|
.lineLimit(-1)
|
||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
|
|
||||||
Text("Card Animation")
|
Text("Card Animation")
|
||||||
.color(Color(hue: 0.498, saturation: 0.609, brightness: 1.0))
|
.foregroundColor(Color(hue: 0.498, saturation: 0.609, brightness: 1.0))
|
||||||
.fontWeight(.bold)
|
.fontWeight(.bold)
|
||||||
.font(.title)
|
.font(.title)
|
||||||
.padding(.bottom, show ? 100 : 20)
|
.padding(.bottom, show ? 100 : 20)
|
||||||
|
|||||||
@@ -10,11 +10,11 @@ import SwiftUI
|
|||||||
import Combine
|
import Combine
|
||||||
|
|
||||||
final class UserData: BindableObject {
|
final class UserData: BindableObject {
|
||||||
let didChange = PassthroughSubject<UserData, Never>()
|
let willChange = PassthroughSubject<UserData, Never>()
|
||||||
|
|
||||||
var notes = NoteData.shared.notes {
|
var notes = NoteData.shared.notes {
|
||||||
didSet {
|
didSet {
|
||||||
didChange.send(self)
|
willChange.send(self)
|
||||||
NoteData.shared.notes = notes
|
NoteData.shared.notes = notes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ struct NoteList : View {
|
|||||||
#if DEBUG
|
#if DEBUG
|
||||||
struct NoteList_Previews : PreviewProvider {
|
struct NoteList_Previews : PreviewProvider {
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
ForEach(["iPhone SE", "iPhone XS Max"].identified(by: \.self)) { deviceName in
|
ForEach(["iPhone SE", "iPhone XS Max"], id: \.self) { deviceName in
|
||||||
NoteList()
|
NoteList()
|
||||||
.environmentObject(UserData())
|
.environmentObject(UserData())
|
||||||
.previewDevice(PreviewDevice(rawValue: deviceName))
|
.previewDevice(PreviewDevice(rawValue: deviceName))
|
||||||
|
|||||||
@@ -9,23 +9,23 @@ import SwiftUI
|
|||||||
import Combine
|
import Combine
|
||||||
|
|
||||||
final class UserData: BindableObject {
|
final class UserData: BindableObject {
|
||||||
let didChange = PassthroughSubject<UserData, Never>()
|
let willChange = PassthroughSubject<UserData, Never>()
|
||||||
|
|
||||||
var showFavoriteOnly = false {
|
var showFavoriteOnly = false {
|
||||||
didSet {
|
didSet {
|
||||||
didChange.send(self)
|
willChange.send(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var videos = videoList {
|
var videos = videoList {
|
||||||
didSet {
|
didSet {
|
||||||
didChange.send(self)
|
willChange.send(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var currentVideo = videoList[0] {
|
var currentVideo = videoList[0] {
|
||||||
didSet {
|
didSet {
|
||||||
didChange.send(self)
|
willChange.send(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ struct TitleText: View {
|
|||||||
let text: String
|
let text: String
|
||||||
var body: some View {
|
var body: some View {
|
||||||
return Text(text)
|
return Text(text)
|
||||||
.color(.primary)
|
.foregroundColor(.primary)
|
||||||
.bold()
|
.bold()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -81,6 +81,6 @@ struct DescriptionText : View {
|
|||||||
var body: some View {
|
var body: some View {
|
||||||
return Text(text)
|
return Text(text)
|
||||||
.font(.footnote).fontWeight(.semibold)
|
.font(.footnote).fontWeight(.semibold)
|
||||||
.color(.secondary)
|
.foregroundColor(.secondary)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -20,7 +20,7 @@ struct CategoryRow: View {
|
|||||||
|
|
||||||
ScrollView(.horizontal) {
|
ScrollView(.horizontal) {
|
||||||
HStack(alignment: .top, spacing: 0) {
|
HStack(alignment: .top, spacing: 0) {
|
||||||
ForEach(self.items.identified(by: \.name)) { landmark in
|
ForEach(self.items, id: \.name) { landmark in
|
||||||
NavigationLink(
|
NavigationLink(
|
||||||
destination: LandmarkDetail(
|
destination: LandmarkDetail(
|
||||||
landmark: landmark
|
landmark: landmark
|
||||||
@@ -45,7 +45,7 @@ struct CategoryItem: View {
|
|||||||
.renderingMode(.original)
|
.renderingMode(.original)
|
||||||
.cornerRadius(5)
|
.cornerRadius(5)
|
||||||
Text(landmark.name)
|
Text(landmark.name)
|
||||||
.color(.primary)
|
.foregroundColor(.primary)
|
||||||
.font(.caption)
|
.font(.caption)
|
||||||
}
|
}
|
||||||
.padding(.leading, 15)
|
.padding(.leading, 15)
|
||||||
|
|||||||
+2
-2
@@ -23,13 +23,13 @@ struct HikeDetail: View {
|
|||||||
.frame(height: 200, alignment: .center)
|
.frame(height: 200, alignment: .center)
|
||||||
|
|
||||||
HStack(spacing: 25) {
|
HStack(spacing: 25) {
|
||||||
ForEach(buttons.identified(by: \.0)) { value in
|
ForEach(buttons, id: \.0) { value in
|
||||||
Button(action: {
|
Button(action: {
|
||||||
self.dataToShow = value.1
|
self.dataToShow = value.1
|
||||||
}) {
|
}) {
|
||||||
Text(verbatim: value.0)
|
Text(verbatim: value.0)
|
||||||
.font(.system(size: 15))
|
.font(.system(size: 15))
|
||||||
.color(value.1 == self.dataToShow
|
.foregroundColor(value.1 == self.dataToShow
|
||||||
? Color.gray
|
? Color.gray
|
||||||
: Color.accentColor)
|
: Color.accentColor)
|
||||||
.animation(nil)
|
.animation(nil)
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ struct HikeView: View {
|
|||||||
var transition: AnyTransition {
|
var transition: AnyTransition {
|
||||||
let insertion = AnyTransition.move(edge: .trailing)
|
let insertion = AnyTransition.move(edge: .trailing)
|
||||||
.combined(with: .opacity)
|
.combined(with: .opacity)
|
||||||
let removal = AnyTransition.scale()
|
let removal = AnyTransition.scale(scale: 0.0)
|
||||||
.combined(with: .opacity)
|
.combined(with: .opacity)
|
||||||
return .asymmetric(insertion: insertion, removal: removal)
|
return .asymmetric(insertion: insertion, removal: removal)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ struct CategoryHome: View {
|
|||||||
.clipped()
|
.clipped()
|
||||||
.listRowInsets(EdgeInsets())
|
.listRowInsets(EdgeInsets())
|
||||||
|
|
||||||
ForEach(categories.keys.sorted().identified(by: \.self)) { key in
|
ForEach(categories.keys.sorted(), id: \.self) { key in
|
||||||
CategoryRow(categoryName: key, items: self.categories[key]!)
|
CategoryRow(categoryName: key, items: self.categories[key]!)
|
||||||
}
|
}
|
||||||
.listRowInsets(EdgeInsets())
|
.listRowInsets(EdgeInsets())
|
||||||
|
|||||||
+1
-1
@@ -35,7 +35,7 @@ struct LandmarkList: View {
|
|||||||
#if DEBUG
|
#if DEBUG
|
||||||
struct LandmarksList_Previews: PreviewProvider {
|
struct LandmarksList_Previews: PreviewProvider {
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
ForEach(["iPhone SE", "iPhone XS Max"].identified(by: \.self)) { deviceName in
|
ForEach(["iPhone SE", "iPhone XS Max"], id: \.self) { deviceName in
|
||||||
LandmarkList()
|
LandmarkList()
|
||||||
.previewDevice(PreviewDevice(rawValue: deviceName))
|
.previewDevice(PreviewDevice(rawValue: deviceName))
|
||||||
.previewDisplayName(deviceName)
|
.previewDisplayName(deviceName)
|
||||||
|
|||||||
+4
-3
@@ -9,17 +9,18 @@ import Combine
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
final class UserData: BindableObject {
|
final class UserData: BindableObject {
|
||||||
let didChange = PassthroughSubject<UserData, Never>()
|
|
||||||
|
let willChange = PassthroughSubject<UserData, Never>()
|
||||||
|
|
||||||
var showFavoritesOnly = false {
|
var showFavoritesOnly = false {
|
||||||
didSet {
|
didSet {
|
||||||
didChange.send(self)
|
willChange.send(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var landmarks = landmarkData {
|
var landmarks = landmarkData {
|
||||||
didSet {
|
didSet {
|
||||||
didChange.send(self)
|
willChange.send(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -26,7 +26,7 @@ struct ProfileEditor: View {
|
|||||||
Text("Seasonal Photo").bold()
|
Text("Seasonal Photo").bold()
|
||||||
|
|
||||||
SegmentedControl(selection: $profile.seasonalPhoto) {
|
SegmentedControl(selection: $profile.seasonalPhoto) {
|
||||||
ForEach(Profile.Season.allCases.identified(by: \.self)) { season in
|
ForEach(Profile.Season.allCases, id: \.self) { season in
|
||||||
Text(season.rawValue).tag(season)
|
Text(season.rawValue).tag(season)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
|
func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
|
||||||
print("Continuing \(userActivity.userInfo?["count"])")
|
print("Continuing \(String(describing: userActivity.userInfo?["count"]))")
|
||||||
}
|
}
|
||||||
|
|
||||||
func scene(_ scene: UIScene, didUpdate userActivity: NSUserActivity) {
|
func scene(_ scene: UIScene, didUpdate userActivity: NSUserActivity) {
|
||||||
|
|||||||
Reference in New Issue
Block a user