Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

975 improve iphone launch sequence new #1000

Merged
merged 43 commits into from
Oct 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
8b4b541
Add SplashScreen
BPerlakiH Sep 12, 2024
ee08110
Handle loading state for iPhone
BPerlakiH Sep 12, 2024
ef506a5
Fixlint
BPerlakiH Sep 12, 2024
586e8ce
Fix post loading state
BPerlakiH Sep 12, 2024
f4711f2
Centered logo loading
BPerlakiH Sep 14, 2024
1ba422f
Loading and LogoViews
BPerlakiH Sep 14, 2024
3577a0d
Clean up assets, align welcome screen
BPerlakiH Sep 14, 2024
bd1adcf
exclude splash from macOS
BPerlakiH Sep 15, 2024
99b2efb
Move Kiwix specific storyboard to separate folder
BPerlakiH Sep 17, 2024
8da2003
Revert the naming to common welcomeLogo
BPerlakiH Sep 17, 2024
d22b558
Replace image, fix image resize
BPerlakiH Sep 21, 2024
6ad3ca8
Add SplashScreen
BPerlakiH Sep 12, 2024
1fd7c2b
Handle loading state for iPhone
BPerlakiH Sep 12, 2024
93e35f4
Fixlint
BPerlakiH Sep 12, 2024
ec880a1
Centered logo loading
BPerlakiH Sep 14, 2024
4417548
Clean up assets, align welcome screen
BPerlakiH Sep 14, 2024
9027601
Move Kiwix specific storyboard to separate folder
BPerlakiH Sep 17, 2024
11059d5
Revert the naming to common welcomeLogo
BPerlakiH Sep 17, 2024
7d753b8
Replace image, fix image resize
BPerlakiH Sep 21, 2024
f2555fa
Revert safeArea for webview
BPerlakiH Sep 21, 2024
e1a350d
Update to NavigationSplitView for macOS
BPerlakiH Sep 29, 2024
06f6368
Change to one loader, and Fetching Catalog text
BPerlakiH Sep 29, 2024
77db59a
Revert
BPerlakiH Sep 29, 2024
813e07e
Fixup
BPerlakiH Sep 29, 2024
15fe200
Start with collapsed state for iPad/macOS
BPerlakiH Sep 29, 2024
b3ab2ce
Hide tab for iPad on loading, when there's no local ZIM files
BPerlakiH Sep 29, 2024
672779a
Clean up
BPerlakiH Sep 30, 2024
747eb1a
Use text as progress
BPerlakiH Oct 2, 2024
8ff9a08
Align logo
BPerlakiH Oct 6, 2024
cac1ec2
Use resizer
BPerlakiH Oct 6, 2024
c2cfb40
Add docs and refactor
BPerlakiH Oct 6, 2024
1c5815a
Fixlint
BPerlakiH Oct 6, 2024
8e0667e
Fixlint and update comments
BPerlakiH Oct 6, 2024
29d9007
Use 300 logo width for regular
BPerlakiH Oct 6, 2024
00768be
Add the same constraints to story board
BPerlakiH Oct 6, 2024
bd9d110
Remove empty file
BPerlakiH Oct 8, 2024
fdbcafb
Max logo width on macOS
BPerlakiH Oct 8, 2024
8f442b6
Revert LibraryViewModel
BPerlakiH Oct 8, 2024
bf9a039
Move the initial loading state into Welcome view
BPerlakiH Oct 9, 2024
8503871
Move hasSeenCategories to defaults, change library tab order
BPerlakiH Oct 9, 2024
9ca8979
Add safety path for upgrading user
BPerlakiH Oct 9, 2024
78f5f7d
Vertical center the logo and button block
BPerlakiH Oct 9, 2024
43f104e
Make space for error message when using compact height
BPerlakiH Oct 9, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion App/App_iOS.swift
Original file line number Diff line number Diff line change
Expand Up @@ -123,9 +123,17 @@ struct Kiwix: App {

private struct RootView: UIViewControllerRepresentable {
@EnvironmentObject private var navigation: NavigationViewModel
@FetchRequest(
sortDescriptors: [NSSortDescriptor(keyPath: \ZimFile.size, ascending: false)],
predicate: ZimFile.openedPredicate,
animation: .easeInOut
) private var zimFiles: FetchedResults<ZimFile>

func makeUIViewController(context: Context) -> SplitViewController {
SplitViewController(navigationViewModel: navigation)
SplitViewController(
navigationViewModel: navigation,
hasZimFiles: !zimFiles.isEmpty
)
}

func updateUIViewController(_ controller: SplitViewController, context: Context) {
Expand Down
11 changes: 2 additions & 9 deletions App/App_macOS.swift
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ struct RootView: View {
private let tabCloses = NotificationCenter.default.publisher(for: NSWindow.willCloseNotification)

var body: some View {
NavigationView {
NavigationSplitView {
List(selection: $navigation.currentItem) {
ForEach(primaryItems, id: \.self) { navigationItem in
Label(navigationItem.name, systemImage: navigationItem.icon)
Expand All @@ -124,14 +124,7 @@ struct RootView: View {
}
}
.frame(minWidth: 150)
.toolbar {
Button {
guard let responder = NSApp.keyWindow?.firstResponder else { return }
responder.tryToPerform(#selector(NSSplitViewController.toggleSidebar(_:)), with: nil)
} label: {
Image(systemName: "sidebar.leading")
}.help("app_macos_navigation.show_sidebar".localized)
}
} detail: {
switch navigation.currentItem {
case .loading:
LoadingView()
Expand Down
46 changes: 30 additions & 16 deletions App/CompactViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,11 @@ final class CompactViewController: UIHostingController<AnyView>, UISearchControl

private var trailingNavItemGroups: [UIBarButtonItemGroup] = []
private var rightNavItem: UIBarButtonItem?
private let navigation: NavigationViewModel
private var navigationItemObserver: AnyCancellable?

init() {
init(navigation: NavigationViewModel) {
self.navigation = navigation
searchViewModel = SearchViewModel()
let searchResult = SearchResults().environmentObject(searchViewModel)
searchController = UISearchController(searchResultsController: UIHostingController(rootView: searchResult))
Expand All @@ -47,8 +50,23 @@ final class CompactViewController: UIHostingController<AnyView>, UISearchControl
override func viewDidLoad() {
super.viewDidLoad()

navigationItemObserver = navigation.$currentItem
.receive(on: DispatchQueue.main)
.sink(receiveValue: { [weak self] currentItem in
if currentItem != .loading {
self?.navigationController?.isToolbarHidden = false
self?.navigationController?.isNavigationBarHidden = false
// listen to only the first change from .loading to something else
self?.navigationItemObserver?.cancel()
}
})

// the .loading initial state:
navigationController?.isToolbarHidden = true
navigationController?.isNavigationBarHidden = true
// eof .loading initial state

definesPresentationContext = true
navigationController?.isToolbarHidden = false
navigationController?.toolbar.scrollEdgeAppearance = {
let apperance = UIToolbarAppearance()
apperance.configureWithDefaultBackground()
Expand Down Expand Up @@ -117,17 +135,11 @@ private struct CompactView: View {
@EnvironmentObject private var navigation: NavigationViewModel
@State private var presentedSheet: PresentedSheet?

private enum PresentedSheet: Identifiable {
case library(LibraryTabItem?)
private enum PresentedSheet: String, Identifiable {
case library
case settings

var id: String {
switch self {
case let .library(libraryItem):
return "library-\(String(describing: libraryItem))"
case .settings:
return "settings"
}
rawValue
}
}

Expand All @@ -136,10 +148,12 @@ private struct CompactView: View {
}

var body: some View {
if case let .tab(tabID) = navigation.currentItem {
if case .loading = navigation.currentItem {
LoadingView()
} else if case let .tab(tabID) = navigation.currentItem {
Content(tabID: tabID, showLibrary: {
if presentedSheet == nil {
presentedSheet = .library(.categories)
presentedSheet = .library
} else {
// there's a sheet already presented by the user
// do nothing
Expand All @@ -161,7 +175,7 @@ private struct CompactView: View {
Spacer()
if FeatureFlags.hasLibrary {
Button {
presentedSheet = .library(nil)
presentedSheet = .library
} label: {
Label("common.tab.menu.library".localized, systemImage: "folder")
}
Expand All @@ -178,8 +192,8 @@ private struct CompactView: View {
.environmentObject(BrowserViewModel.getCached(tabID: tabID))
.sheet(item: $presentedSheet) { presentedSheet in
switch presentedSheet {
case .library(let tabItem):
Library(dismiss: dismiss, tabItem: tabItem)
case .library:
Library(dismiss: dismiss)
case .settings:
NavigationView {
Settings().toolbar {
Expand Down
34 changes: 26 additions & 8 deletions App/SplitViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,14 @@ final class SplitViewController: UISplitViewController {
let navigationViewModel: NavigationViewModel
private var navigationItemObserver: AnyCancellable?
private var openURLObserver: NSObjectProtocol?
private var hasZimFiles: Bool

init(navigationViewModel: NavigationViewModel) {
init(
navigationViewModel: NavigationViewModel,
hasZimFiles: Bool
) {
self.navigationViewModel = navigationViewModel
self.hasZimFiles = hasZimFiles
super.init(style: .doubleColumn)
}

Expand All @@ -41,33 +46,46 @@ final class SplitViewController: UISplitViewController {
override func viewDidLoad() {
super.viewDidLoad()

// start with collapsed state for .loading
preferredDisplayMode = .secondaryOnly

// setup controllers
setViewController(UINavigationController(rootViewController: CompactViewController()), for: .compact)
setViewController(
UINavigationController(
rootViewController: CompactViewController(navigation: navigationViewModel)
),
for: .compact
)
setViewController(SidebarViewController(), for: .primary)
setSecondaryController()

// observers
navigationItemObserver = navigationViewModel.$currentItem
.receive(on: DispatchQueue.main) // needed to postpones sink after navigationViewModel.currentItem updates
.dropFirst()
.sink { [weak self] _ in
.sink { [weak self] currentItem in
if let sidebarViewController = self?.viewController(for: .primary) as? SidebarViewController {
sidebarViewController.updateSelection()
}
if self?.traitCollection.horizontalSizeClass == .regular {
self?.setSecondaryController()
}
if self?.hasZimFiles == true, currentItem != .loading {
self?.preferredDisplayMode = .automatic
}
}
openURLObserver = NotificationCenter.default.addObserver(
forName: .openURL, object: nil, queue: nil
) { [weak self] notification in
guard let url = notification.userInfo?["url"] as? URL else { return }
let inNewTab = notification.userInfo?["inNewTab"] as? Bool ?? false
if !inNewTab, case let .tab(tabID) = self?.navigationViewModel.currentItem {
BrowserViewModel.getCached(tabID: tabID).load(url: url)
} else {
guard let tabID = self?.navigationViewModel.createTab() else { return }
BrowserViewModel.getCached(tabID: tabID).load(url: url)
Task { @MainActor in
if !inNewTab, case let .tab(tabID) = self?.navigationViewModel.currentItem {
BrowserViewModel.getCached(tabID: tabID).load(url: url)
} else {
guard let tabID = self?.navigationViewModel.createTab() else { return }
BrowserViewModel.getCached(tabID: tabID).load(url: url)
}
}
}
}
Expand Down
85 changes: 85 additions & 0 deletions Kiwix/SplashScreenKiwix.storyboard
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="23094" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<device id="retina4_0" orientation="landscape" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="23084"/>
<capability name="System colors in document resources" minToolsVersion="11.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="EHf-IW-A2E">
<objects>
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="UTd-Wd-2hu"/>
<viewControllerLayoutGuide type="bottom" id="5aq-KH-MQP"/>
</layoutGuides>
<view key="view" userInteractionEnabled="NO" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" id="Ze5-6b-2t3">
<rect key="frame" x="0.0" y="0.0" width="568" height="320"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="welcomeLogo" adjustsImageSizeForAccessibilityContentSizeCategory="YES" translatesAutoresizingMaskIntoConstraints="NO" id="aq8-ue-tYD" userLabel="Logo">
<rect key="frame" x="142" y="82" width="284" height="92"/>
<constraints>
<constraint firstAttribute="width" constant="300" id="zyG-3z-VNV"/>
</constraints>
<variation key="default">
<mask key="constraints">
<exclude reference="zyG-3z-VNV"/>
</mask>
</variation>
<variation key="widthClass=regular">
<mask key="constraints">
<include reference="zyG-3z-VNV"/>
</mask>
</variation>
</imageView>
</subviews>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<constraints>
<constraint firstItem="aq8-ue-tYD" firstAttribute="height" secondItem="Ze5-6b-2t3" secondAttribute="height" multiplier="0.5" id="S68-g2-nFH"/>
<constraint firstItem="aq8-ue-tYD" firstAttribute="width" secondItem="Ze5-6b-2t3" secondAttribute="width" multiplier="0.5" id="TF7-1V-ah2"/>
<constraint firstItem="aq8-ue-tYD" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="m7x-hm-LnP"/>
<constraint firstItem="aq8-ue-tYD" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="centerY" constant="-58" id="tmp-PG-GZz">
<variation key="heightClass=compact" constant="-32"/>
</constraint>
<constraint firstItem="aq8-ue-tYD" firstAttribute="height" secondItem="Ze5-6b-2t3" secondAttribute="height" constant="-228" id="yNt-tV-blG"/>
</constraints>
<variation key="default">
<mask key="constraints">
<exclude reference="TF7-1V-ah2"/>
<exclude reference="S68-g2-nFH"/>
<exclude reference="yNt-tV-blG"/>
</mask>
</variation>
<variation key="heightClass=compact">
<mask key="constraints">
<include reference="yNt-tV-blG"/>
</mask>
</variation>
<variation key="heightClass=regular">
<mask key="constraints">
<include reference="S68-g2-nFH"/>
</mask>
</variation>
<variation key="widthClass=compact">
<mask key="constraints">
<include reference="TF7-1V-ah2"/>
</mask>
</variation>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="52.761627906976742" y="375"/>
</scene>
</scenes>
<resources>
<image name="welcomeLogo" width="192" height="140"/>
<systemColor name="systemBackgroundColor">
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</systemColor>
</resources>
</document>
9 changes: 8 additions & 1 deletion Model/Brand.swift
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,12 @@ enum AppType {
enum Brand {
static let appName: String = Config.value(for: .displayName) ?? "Kiwix"
static let appStoreId: String = Config.value(for: .appStoreID) ?? "id997079563"
static let welcomeLogoImageName: String = "welcomeLogo"
static let loadingLogoImage: String = "welcomeLogo"
static let loadingLogoWidth: Int = Config.value(for: .logoWidth) ?? 192
static let loadingLogoHeight: Int = Config.value(for: .logoHeight) ?? 140
static var loadingLogoSize: CGSize {
CGSize(width: loadingLogoWidth, height: loadingLogoHeight)
}
static let aboutText: String = Config.value(for: .aboutText) ?? "settings.about.description".localized
static let aboutWebsite: String = Config.value(for: .aboutWebsite) ?? "https://www.kiwix.org"

Expand Down Expand Up @@ -79,6 +84,8 @@ enum Config: String {
case showSearchSnippetInSettings = "SETTINGS_SHOW_SEARCH_SNIPPET"
case aboutText = "CUSTOM_ABOUT_TEXT"
case aboutWebsite = "CUSTOM_ABOUT_WEBSITE"
case logoWidth = "LOGO_WIDTH"
case logoHeight = "LOGO_HEIGHT"

static func value<T>(for key: Config) -> T? where T: LosslessStringConvertible {
guard let object = Bundle.main.object(forInfoDictionaryKey: key.rawValue) else {
Expand Down
36 changes: 36 additions & 0 deletions Model/Utilities/Resizer.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// This file is part of Kiwix for iOS & macOS.
//
// Kiwix is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// any later version.
//
// Kiwix is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Kiwix; If not, see https://www.gnu.org/licenses/.

import Foundation

enum Resizer {

static func fit(_ size: CGSize, into maxSize: CGSize) -> CGSize {
let ratio = size.ratio
if maxSize.ratio <= ratio {
// subject is horizontal
return CGSize(width: maxSize.width, height: maxSize.width / ratio)
} else {
return CGSize(width: maxSize.height * ratio, height: maxSize.height)
}
}
}

extension CGSize {
var ratio: CGFloat {
guard height != 0 else { return 1 }
return width / height
}
}
25 changes: 24 additions & 1 deletion Support/Assets.xcassets/welcomeLogo.imageset/Contents.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,35 @@
{
"images" : [
{
"filename" : "Kiwix_logo_v3.svg",
"filename" : "vertical-logo-light.svg",
"idiom" : "universal"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "light"
}
],
"filename" : "vertical-logo-light 1.svg",
"idiom" : "universal"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"filename" : "vertical-logo-dark.svg",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"preserves-vector-representation" : true
}
}
Loading