Skip to content

Commit

Permalink
feat: Add App Favorites List
Browse files Browse the repository at this point in the history
  • Loading branch information
iHTCboy committed Jun 24, 2023
1 parent c67281a commit c9fe03c
Show file tree
Hide file tree
Showing 8 changed files with 213 additions and 15 deletions.
12 changes: 12 additions & 0 deletions iAppStore.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@
6D738E2E2779736B00A4A76E /* SettingHome.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D738E2D2779736B00A4A76E /* SettingHome.swift */; };
6D738E322779743D00A4A76E /* Color.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D738E312779743D00A4A76E /* Color.swift */; };
6D7A39492A46968100CA7F6E /* QRCodeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D7A39482A46968100CA7F6E /* QRCodeView.swift */; };
6D7A394B2A46BDA900CA7F6E /* AppFavoritesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D7A394A2A46BDA900CA7F6E /* AppFavoritesView.swift */; };
6D7A394D2A46C79F00CA7F6E /* AppFavoritesModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D7A394C2A46C79F00CA7F6E /* AppFavoritesModel.swift */; };
6D7A394F2A46C7E500CA7F6E /* AppFavorite.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D7A394E2A46C7E500CA7F6E /* AppFavorite.swift */; };
6D89AF85277879190075E66F /* iAppStoreApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D89AF84277879190075E66F /* iAppStoreApp.swift */; };
6D89AF89277879190075E66F /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D89AF88277879190075E66F /* Assets.xcassets */; };
6D89AF8C277879190075E66F /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D89AF8B277879190075E66F /* Preview Assets.xcassets */; };
Expand Down Expand Up @@ -85,6 +88,9 @@
6D738E2D2779736B00A4A76E /* SettingHome.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingHome.swift; sourceTree = "<group>"; };
6D738E312779743D00A4A76E /* Color.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Color.swift; sourceTree = "<group>"; };
6D7A39482A46968100CA7F6E /* QRCodeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRCodeView.swift; sourceTree = "<group>"; };
6D7A394A2A46BDA900CA7F6E /* AppFavoritesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppFavoritesView.swift; sourceTree = "<group>"; };
6D7A394C2A46C79F00CA7F6E /* AppFavoritesModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppFavoritesModel.swift; sourceTree = "<group>"; };
6D7A394E2A46C7E500CA7F6E /* AppFavorite.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppFavorite.swift; sourceTree = "<group>"; };
6D89AF81277879190075E66F /* iAppStore.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = iAppStore.app; sourceTree = BUILT_PRODUCTS_DIR; };
6D89AF84277879190075E66F /* iAppStoreApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = iAppStoreApp.swift; sourceTree = "<group>"; };
6D89AF88277879190075E66F /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
Expand Down Expand Up @@ -193,6 +199,7 @@
6D738E2D2779736B00A4A76E /* SettingHome.swift */,
6D26AAC1278420CB003F82BF /* AboutAppView.swift */,
6D0809DB29FB576100D12E21 /* AppleServicesView.swift */,
6D7A394A2A46BDA900CA7F6E /* AppFavoritesView.swift */,
);
path = setting;
sourceTree = "<group>";
Expand Down Expand Up @@ -305,6 +312,7 @@
6DB3B789277D748400E8626F /* AppRankModel.swift */,
6DB3B78E277D756B00E8626F /* AppDetailModel.swift */,
6D490E5927833C4D00B5DD80 /* AppSubscripeModel.swift */,
6D7A394C2A46C79F00CA7F6E /* AppFavoritesModel.swift */,
);
path = ViewModels;
sourceTree = "<group>";
Expand All @@ -315,6 +323,7 @@
6DB3B790277D757400E8626F /* AppRank.swift */,
6D95DC6D27804AAD00EE8B54 /* AppDetail.swift */,
6D490E5727833B1C00B5DD80 /* AppSubscripe.swift */,
6D7A394E2A46C7E500CA7F6E /* AppFavorite.swift */,
);
path = Models;
sourceTree = "<group>";
Expand Down Expand Up @@ -471,6 +480,7 @@
6D605A17278B15950001C69F /* ShareSheet.swift in Sources */,
6D95DC6B2780292800EE8B54 /* RankCellView.swift in Sources */,
6C51177627A2755100D5E21D /* NetworkMonitor.swift in Sources */,
6D7A394D2A46C79F00CA7F6E /* AppFavoritesModel.swift in Sources */,
6D738E2E2779736B00A4A76E /* SettingHome.swift in Sources */,
6D738E2A2779734700A4A76E /* SearchHome.swift in Sources */,
6D0809DC29FB576100D12E21 /* AppleServicesView.swift in Sources */,
Expand All @@ -490,6 +500,8 @@
6C51176C27A00D9C00D5E21D /* LocalFileManager.swift in Sources */,
6D605A15278B15850001C69F /* AppContextMenu.swift in Sources */,
6DB3B782277D6CE700E8626F /* Constants.swift in Sources */,
6D7A394F2A46C7E500CA7F6E /* AppFavorite.swift in Sources */,
6D7A394B2A46BDA900CA7F6E /* AppFavoritesView.swift in Sources */,
6D490E56278328E400B5DD80 /* SubscriptionAddView.swift in Sources */,
6D0809DE29FB5FA500D12E21 /* SafariView.swift in Sources */,
6D95DC6E27804AAD00EE8B54 /* AppDetail.swift in Sources */,
Expand Down
14 changes: 14 additions & 0 deletions iAppStore/Models/AppFavorite.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//
// AppFavorite.swift
// iAppStore
//
// Created by iHTCboy on 2023/6/24.
// Copyright © 2023 37 Mobile Games. All rights reserved.
//

import Foundation

struct AppFavorite: Codable {
var appId: String
var regionName: String
}
17 changes: 17 additions & 0 deletions iAppStore/ViewModels/AppDetailModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -63,4 +63,21 @@ class AppDetailModel: ObservableObject {
}
}
}

/// looup app id
func lookupAppId(_ appId: String, _ regionName: String) {
let regionId = TSMGConstants.regionTypeListIds[regionName] ?? "cn"
let endpoint = APIService.Endpoint.lookupApp(appid: appId, country: regionId)

APIService.shared.POST(endpoint: endpoint, params: nil) { (result: Result<AppDetailM, APIService.APIError>) in
switch result {
case let .success(response):
if let app = response.results.first {
self.results.append(app)
}
case .failure(_):
break
}
}
}
}
60 changes: 60 additions & 0 deletions iAppStore/ViewModels/AppFavoritesModel.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
//
// AppFavoritesModel.swift
// iAppStore
//
// Created by iHTCboy on 2023/6/24.
// Copyright © 2023 37 Mobile Games. All rights reserved.
//

import Foundation

class AppFavoritesModel: ObservableObject {

public static let shared = AppFavoritesModel()

func search(_ appId: String) -> AppFavorite? {
let favorites = appFavorites()
return favorites.first(where: { $0.appId == appId })
}

func add(_ app: AppFavorite) {
var favorites = appFavorites()
if let index = favorites.firstIndex(where: { $0.appId == app.appId }) {
favorites[index] = app
} else {
favorites.append(app)
}
saveFavorites(favorites)
}

/// 删除
/// - Parameter appId: app id
/// - Returns: 1:删除成功,0:删除失败,-1:未找到删除元素
@discardableResult
func remove(appId: String) -> Int {
var favorites = appFavorites()
if let index = favorites.firstIndex(where: { $0.appId == appId }) {
favorites.remove(at: index)
saveFavorites(favorites)
return 1
}
return -1
}

func appFavorites() -> [AppFavorite] {
let userDefaults = UserDefaults.standard
if let data = userDefaults.data(forKey: "AppFavorites") {
if let decodedData = try? JSONDecoder().decode([AppFavorite].self, from: data) {
return decodedData
}
}
return []
}

func saveFavorites(_ favorites: [AppFavorite]) {
let userDefaults = UserDefaults.standard
if let encodedData = try? JSONEncoder().encode(favorites) {
userDefaults.set(encodedData, forKey: "AppFavorites")
}
}
}
9 changes: 5 additions & 4 deletions iAppStore/components/rankLists/AppDetailContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -529,11 +529,12 @@ struct AppDetailFooterCellView: View {

struct AppDetailContentView_Previews: PreviewProvider {
static var previews: some View {
let model = { () -> AppDetailModel in
let model = AppDetailModel()
let model = AppDetailModel()
NavigationView {
AppDetailContentView(appModel: model)
}
.onAppear {
model.searchAppData("1669437212", nil, "中国")
return model
}
AppDetailContentView(appModel: model())
}
}
38 changes: 30 additions & 8 deletions iAppStore/components/rankLists/AppDetailView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ struct AppDetailView: View {

@StateObject private var appModel = AppDetailModel()
@State private var isShowingQRCode = false
@State private var isAppFavorites = false

var body: some View {

Expand All @@ -24,30 +25,51 @@ struct AppDetailView: View {
}
.navigationBarTitle(item?.imName.label ?? appModel.app?.trackName ?? "", displayMode: .large)
.navigationBarBackButtonHidden(false)
.navigationBarItems(trailing:
.navigationBarItems(trailing: HStack(spacing: 5) {
Button(action: handleFavoriteButton) {
if isAppFavorites {
Image(systemName: "star.fill")
.foregroundColor(.yellow)
} else {
Image(systemName: "star")
}
}
Button(action: {
isShowingQRCode = true
}) {
Image(systemName: "qrcode")
}
Link(destination: URL(string: appModel.app?.trackViewUrl ?? item?.id.label ?? "https://apple.com")!) {
Image(systemName: "icloud.and.arrow.down").font(.subheadline)
Button(action: {
isShowingQRCode = true
}) {
Image(systemName: "qrcode")
.font(.subheadline)
}
}
})
.sheet(isPresented: $isShowingQRCode) {
QRCodeView(title: "扫一扫下载", subTitle: "App Store 上的“\(item?.imName.label ?? "")", qrCodeContent: item?.id.label ?? "error", isShowingQRCode: $isShowingQRCode)
}
.onAppear {
isAppFavorites = AppFavoritesModel.shared.search(appId) != nil
if appModel.app == nil {
appModel.searchAppData(appId, nil, regionName)
}
}
}

// 处理收藏按钮的动作
func handleFavoriteButton() {
if isAppFavorites {
AppFavoritesModel.shared.remove(appId: appId)
} else {
AppFavoritesModel.shared.add(AppFavorite(appId: appId, regionName: regionName))
}
isAppFavorites.toggle()
}
}


struct AppDetailView_Previews: PreviewProvider {
static var previews: some View {
AppDetailView(appId: "1669437212", regionName: "中国")
NavigationView {
AppDetailView(appId: "1669437212", regionName: "中国")
}
}
}
65 changes: 65 additions & 0 deletions iAppStore/components/setting/AppFavoritesView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
//
// AppFavoritesView.swift
// iAppStore
//
// Created by iHTCboy on 2023/6/24.
// Copyright © 2023 37 Mobile Games. All rights reserved.
//

import SwiftUI

struct AppFavoritesView: View {

@StateObject private var appModel = AppDetailModel()

var body: some View {
VStack {
if appModel.results.count == 0 {
EmptyStateView()
} else {
List {
ForEach(appModel.results, id: \.trackId) { item in
let index = appModel.results.firstIndex { $0.trackId == item.trackId }
NavigationLink(destination: AppDetailView(appId: String(item.trackId), regionName: "中国", item: nil)) {
SearchCellView(index: index ?? 0, item: item).frame(height: 110)
}
}
}
}
}
.navigationBarTitle("App 收藏夹")
.navigationBarTitleDisplayMode(.automatic)
.onAppear {
let favorites = AppFavoritesModel.shared.appFavorites()
if appModel.results.count == 0, !favorites.isEmpty {
favorites.forEach { app in
appModel.lookupAppId(app.appId, app.regionName)
}
}
}
}
}

struct EmptyStateView: View {
var body: some View {
Spacer()
Image(systemName: "list.star")
.font(Font.system(size: 60))
.foregroundColor(Color.tsmg_tertiaryLabel)
Spacer()
}
}


struct AppFavoritesView_Previews: PreviewProvider {
static var previews: some View {
NavigationView {
AppFavoritesView()
}
.onAppear {
AppFavoritesModel.shared.add(AppFavorite(appId: "1669437212", regionName: "中国"))
AppFavoritesModel.shared.add(AppFavorite(appId: "989673964", regionName: "中国"))
AppFavoritesModel.shared.add(AppFavorite(appId: "1142110895", regionName: "中国"))
}
}
}
13 changes: 10 additions & 3 deletions iAppStore/components/setting/SettingHome.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,14 @@ struct SettingHome: View {
}
}

Section(header: Text("苹果服务")) {
Section(header: Text("服务")) {
NavigationLink(destination: AppFavoritesView()) {
HStack {
Text("App 收藏夹")
Spacer()
}
.padding([.top, .bottom], 10)
}
NavigationLink(destination: AppleServicesView()) {
HStack {
Text("苹果常用网站")
Expand All @@ -45,7 +52,7 @@ struct SettingHome: View {
Text("关于应用").frame(height: 50)
}
SettingItemCell(linkPage: $linkPage, title: "GitHub 开源", index: items.count)
SettingItemCell(linkPage: $linkPage, title: "37手游iOS技术运营团队", index: items.count + 1)
SettingItemCell(linkPage: $linkPage, title: "37手游移动客户端团队", index: items.count + 1)
}
}
}
Expand Down Expand Up @@ -150,7 +157,7 @@ struct SettingItemCell: View {
case 4:
linkPage = LinkString(url: "https://www.qimai.cn")
case 5:
linkPage = LinkString(url: "https://github.com/37iOS/iAppStore-SwiftUI")
linkPage = LinkString(url: "https://github.com/37MobileTeam/iAppStore-SwiftUI")
case 6:
linkPage = LinkString(url: "https://juejin.cn/user/1002387318511214")
default: break
Expand Down

0 comments on commit c9fe03c

Please sign in to comment.