Skip to content

Commit

Permalink
Merge branch 'mac-1'
Browse files Browse the repository at this point in the history
Conflicts:
	Source/Hollow/View/Components/Avatar.swift
  • Loading branch information
liang2kl committed Apr 26, 2021
2 parents c23a939 + f5e8e38 commit f6b7690
Show file tree
Hide file tree
Showing 120 changed files with 2,264 additions and 698 deletions.
1,387 changes: 964 additions & 423 deletions Source/Hollow.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

128 changes: 3 additions & 125 deletions Source/Hollow/App/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,144 +6,22 @@
// Copyright © 2021 treehollow. All rights reserved.
//

import SwiftUI
import UIKit
import Defaults
import AppCenter
import AppCenterAnalytics
import AppCenterCrashes
import Connectivity

class AppDelegate: UIResponder, UIApplicationDelegate {
// MARK: - UIApplicationDelegate
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
#if !DEBUG
// Start AppCenter services
AppCenter.start(
withAppSecret: "aae3c20c-75f5-4840-96f3-541cd7e6dd88",
services: [Analytics.self, Crashes.self]
)
#endif

Defaults[.customColorSet] = Defaults[.tempCustomColorSet]
Defaults[.applyCustomColorSet] = Defaults[.customColorSet] != nil

// Setup remote notifications
setupRemoteNotifications(application)

// Fetch the lastest config
fetchConfig()

setupApplication(application)
return true
}

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
// Temporarily save the token in defaults. We are not using this
// default except registering or logging in for the first time.
Defaults[.deviceToken] = deviceToken

// Try to send the token to the server, if we have a user token.
if let accessToken = Defaults[.accessToken] {
sendDeviceToken(deviceToken, withAccessToken: accessToken)
}
didRegisterForRemoteNotifications(with: deviceToken)
}

func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
print("Fail to register remote notification with error: \(error.localizedDescription)")
}

#if targetEnvironment(macCatalyst)
override func buildMenu(with builder: UIMenuBuilder) {
builder.remove(menu: .file)
builder.remove(menu: .edit)
builder.remove(menu: .format)
builder.remove(menu: .help)
builder.remove(menu: .services)
builder.remove(menu: .toolbar)
}
#endif
}

// MARK: - Tree Hollow Configuration & Setup
extension AppDelegate {
func setupRemoteNotifications(_ application: UIApplication) {
// Request notification access
let center = UNUserNotificationCenter.current()
center.delegate = self
let authorizationOptions = Constants.Application.requestedNotificationOptions
center.requestAuthorization(options: authorizationOptions) { granted, error in
guard granted else { return }
// Register for APN
DispatchQueue.main.async {
application.registerForRemoteNotifications()
}
}
}

private func sendDeviceToken(_ deviceToken: Data, withAccessToken accessToken: String) {
guard let config = Defaults[.hollowConfig] else { return }
let configuration = UpdateDeviceTokenRequestConfiguration(deviceToken: deviceToken, token: accessToken, apiRoot: config.apiRootUrls)
let request = UpdateDeviceTokenRequest(configuration: configuration)

request.performRequest(completion: { result, error in
if let error = error {
print(error)
// TODO: Handle error
}
})
}

private func fetchConfig() {
guard let hollowType = Defaults[.hollowType] else { return }
var configURL: String? {
switch hollowType {
case .thu: return Constants.HollowConfig.thuConfigURL
case .pku: return Constants.HollowConfig.pkuConfigURL
case .other:
return Defaults[.customConfigURL]
}
}

guard let urlString = configURL else { return }
let request = GetConfigRequest(configuration: GetConfigRequestConfiguration(hollowType: hollowType, customAPIRoot: urlString)!)

request.performRequest(completion: { result, error in
if let _ = error {
// TODO: Handle error
return
}

if let result = result {
// Update the config and test connectivity
Defaults[.hollowConfig] = result
LineSwitchManager.testAll()
}
})
}
}

// MARK: - User Notifications
extension AppDelegate: UNUserNotificationCenterDelegate {
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
let content = response.notification.request.content

if let type = content.userInfo["type"] as? Int, type == 1 {
// System message for type 1
let messageView = MessageView(presented: .constant(true), page: .message, selfDismiss: true)
IntegrationUtilities.presentView(content: { messageView })
} else if let postId = content.userInfo["pid"] as? Int {
let commentId = content.userInfo["cid"] as? Int
IntegrationUtilities.openTemplateDetailView(postId: postId, jumpToComment: commentId)
}

completionHandler()
}

func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {

if notification.request.content.userInfo["delete"] == nil {
completionHandler([.banner, .sound, .list])
} else {
completionHandler([])
}
}
}
6 changes: 6 additions & 0 deletions Source/Hollow/App/AppModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,19 @@

import Combine
import Defaults

#if canImport(Rechability)
import Connectivity
#endif

import SwiftUI

class AppModel: ObservableObject {
private var cancellables = Set<AnyCancellable>()

@Published var isInMainView = Defaults[.accessToken] != nil && Defaults[.hollowConfig] != nil

#if canImport(Rechability)
var connectedToNetwork = Connectivity().status.isConnected

init() {
Expand All @@ -27,4 +32,5 @@ class AppModel: ObservableObject {
})
.store(in: &cancellables)
}
#endif
}
1 change: 1 addition & 0 deletions Source/Hollow/App/AppModelBehaviour.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import SwiftUI
import Defaults
import UserNotifications

/// Modifier for views that take control of the behaviour of the app
/// using the model injected in the environment.
Expand Down
4 changes: 4 additions & 0 deletions Source/Hollow/App/AppModelEnvironment.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,11 @@ extension AppModelEnvironment {
case .tokenExpiredError:
Defaults[.accessToken] = nil
appModelState.shouldShowMainView = false
// FIXME: Show Alert in macOS
#if !os(macOS)
ToastManager.shared.show(configuration: .error(title: nil, body: NSLocalizedString("WELCOMVIEW_TOKEN_EXPIRED_LABEL", comment: "")))
#endif

return true
default: return false
}
Expand Down
51 changes: 38 additions & 13 deletions Source/Hollow/View/Components/Avatar.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,36 +7,61 @@
//

import SwiftUI
import Defaults

struct Avatar: View {
var colors: [Color]
var paddingColor: Color
var resolution: Int
var padding: CGFloat
var name: String
@Default(.usingSimpleAvatar) var usingSimpleAvatar
@Default(.usingOffscreenRender) var usingOffscreenRender

init(foregroundColor: Color, backgroundColor: Color, resolution: Int, padding: CGFloat, hashValue: Int) {
init(foregroundColor: Color, backgroundColor: Color, resolution: Int, padding: CGFloat, hashValue: Int, name: String) {
self.paddingColor = foregroundColor
self.colors = AvatarGenerator.colorData(foregroundColor: foregroundColor, backgroundColor: backgroundColor, resolution: resolution, hashValue: hashValue)
self.resolution = resolution
self.padding = padding
self.name = name
}

var body: some View {
VStack(spacing: 0) {
ForEach(0..<resolution) { x in
HStack(spacing: 0) {
ForEach(0..<resolution) { y in
let index = x * resolution + y
Rectangle()
.foregroundColor(colors[index])
.aspectRatio(1, contentMode: .fill)
if !usingSimpleAvatar {
VStack(spacing: 0) {
ForEach(0..<resolution) { x in
HStack(spacing: 0) {
ForEach(0..<resolution) { y in
let index = x * resolution + y
Rectangle()
.foregroundColor(colors[index])
.aspectRatio(1, contentMode: .fill)
}
}
}
}
.conditionalDrawingGroup(usingOffscreenRender)
.aspectRatio(1, contentMode: .fill)
.padding(padding)
.background(paddingColor)

} else {
ZStack {
Rectangle()
.foregroundColor(paddingColor)
Text(String(name.first ?? " "))
.fontWeight(.heavy)
.font(.system(.body, design: .rounded))
.foregroundColor(.white)
}
.aspectRatio(1, contentMode: .fill)
}
.drawingGroup()
.aspectRatio(1, contentMode: .fill)
.padding(padding)
.background(paddingColor)
}
}

private extension View {
@ViewBuilder func conditionalDrawingGroup(_ apply: Bool) -> some View {
if apply { self.drawingGroup() }
else { self }
}
}
2 changes: 1 addition & 1 deletion Source/Hollow/View/Components/LoadingLabel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// LoadingLabel.swift
// Hollow
//
// Created by 梁业升 on 2021/2/10.
// Created by liang2kl on 2021/2/10.
// Copyright © 2021 treehollow. All rights reserved.
//

Expand Down
2 changes: 1 addition & 1 deletion Source/Hollow/View/Components/SearchBar.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// SearchBar.swift
// Hollow
//
// Created by 梁业升 on 2021/3/3.
// Created by liang2kl on 2021/3/3.
// Copyright © 2021 treehollow. All rights reserved.
//

Expand Down
75 changes: 63 additions & 12 deletions Source/Hollow/View/Hierarchy/Account/SettingsSubViews.swift
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,9 @@ struct OtherSettingsView: View {
OpenURLSettingsView()
#endif

EfficientModeSettingsView()
Section(header: Text("SETTINGSVIEW_OTHER_EXP_FEAT_NAV_TITLE").padding(.horizontal)) {
NavigationLink("SETTINGSVIEW_OTHER_EXP_FEAT_NAV_TITLE", destination: ExperimentalFeaturesView())
}
}
.defaultListStyle()
.navigationBarTitle(NSLocalizedString("SETTINGSVIEW_OTHER_NAV_TITLE", comment: ""))
Expand Down Expand Up @@ -448,20 +450,69 @@ struct OtherSettingsView: View {
}
}

private struct EfficientModeSettingsView: View {
@Default(.enableEfficientMode) var enableEfficientMode
private struct ExperimentalFeaturesView: View {
@Default(.reduceImageQuality) var reduceImageQuality
@Default(.usingOffscreenRender) var usingOffscreenRender
@Default(.usingSimpleAvatar) var usingSimpleAvatar

var body: some View {
Section(
header: Text("SETTINGSVIEW_OTHER_PERFORMANCE_SECTION_HEADER").padding(.horizontal),
footer: Text("SETTINGSVIEW_OTHER_PERFORMANCE_SECTION_FOOTER").padding(.horizontal)) {
HStack {
Text("SETTINGSVIEW_OTHER_EFFICIENT_MODE_ENABLE")
Spacer()
Toggle("", isOn: $enableEfficientMode)
.toggleStyle(SwitchToggleStyle(tint: .tint))
.labelsHidden()
List {
Text("SETTINGSVIEW_OTHER_EXP_FEAT_DESCRIPTION")
.listRowBackground(Color.clear)

Section(
header: Text("SETTINGSVIEW_OTHER_EXP_REDUCE_IMG_QUALITY_HEADER").padding(.horizontal),
footer: Text("SETTINGSVIEW_OTHER_EXP_REDUCE_IMG_QUALITY_FOOTER").padding(.horizontal)) {
HStack {
Text("SETTINGSVIEW_OTHER_EXP_REDUCE_IMG_QUALITY_LABEL")
Spacer()

Toggle("", isOn: $reduceImageQuality)
.toggleStyle(SwitchToggleStyle(tint: .tint))
.labelsHidden()
}
}

Section(
header: Text("SETTINGSVIEW_OTHER_EXP_AVATAR_HEADER").padding(.horizontal),
footer: Text("SETTINGSVIEW_OTHER_EXP_AVATAR_FOOTER").padding(.horizontal)) {
HStack {
Text("SETTINGSVIEW_OTHER_EXP_AVATAR_OFFSCREEN_LABEL")
Spacer()
let isOn = Binding(
get: { usingOffscreenRender },
set: { on in withAnimation {
if on { usingSimpleAvatar = false }
usingOffscreenRender = on
}}
)

Toggle("", isOn: isOn)
.toggleStyle(SwitchToggleStyle(tint: .tint))
.labelsHidden()
}

HStack {
Text("SETTINGSVIEW_OTHER_EXP_AVATAR_SIMPLE_LABEL")
Spacer()

let isOn = Binding(
get: { usingSimpleAvatar },
set: { on in withAnimation {
if on { usingOffscreenRender = false }
usingSimpleAvatar = on
}}
)
Toggle("", isOn: isOn)
.toggleStyle(SwitchToggleStyle(tint: .tint))
.labelsHidden()
}

}

}
.defaultListStyle()
.navigationTitle(NSLocalizedString("SETTINGSVIEW_OTHER_EXP_FEAT_NAV_TITLE", comment: ""))
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ struct _HollowHeaderView<MenuContent: View>: View {
backgroundColor: .white,
resolution: 6,
padding: body37 * 0.1,
hashValue: postData.hash
hashValue: postData.hash,
name: String(postData.postId.string.last ?? " ")
)
// Scale the avatar relative to the font scaling.
.frame(width: body37, height: body37)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,8 @@ struct HollowCommentContentView: View {
backgroundColor: .white,
resolution: resolution,
padding: avatarWidth * 0.1,
hashValue: hash
hashValue: hash,
name: commentData.name
)
.frame(width: avatarWidth)
.clipShape(Circle())
Expand Down
Loading

0 comments on commit f6b7690

Please sign in to comment.