~not/FerryTimetable3

879ab3308cb963811d4352da6dd1a943ddc4a5b1 — b123400 3 years ago 7cb687c resident-mode
Better layout for widget view
M Ferry widget/TodayViewController.swift => Ferry widget/TodayViewController.swift +3 -4
@@ 17,7 17,7 @@ class TodayViewController: UIViewController, NCWidgetProviding, CLLocationManage
    }()
    
    lazy var residentScheduleView = {
        ResidenceSchedulesView(frame: .zero)
        WidgetResidenceSchedulesView(frame: .zero)
    }()
    var location: CLLocation? = nil {
        didSet {


@@ 48,8 48,7 @@ class TodayViewController: UIViewController, NCWidgetProviding, CLLocationManage
    }
    
    func reload() {
        let island = UserDefaults(suiteName: "group.net.b123400.ferriestimetable")?.string(forKey: "widget-island")
            .flatMap { Island.init(rawValue:$0) } ?? Island.centralCheungChau
        let island = ModelManager.shared.homeRoute ?? .centralCheungChau
        let schedule = Schedule(raws: ModelManager.shared.getRaws())
        
        if ModelManager.shared.residentModeReady, let l = location, let direction = ModelManager.shared.residenceDirectionWith(location: l) {


@@ 59,7 58,7 @@ class TodayViewController: UIViewController, NCWidgetProviding, CLLocationManage
                self.scheduleView.removeFromSuperview()
            }
            let ferries = schedule.upcomingFerries(island: island, direction: direction, count: 4)
            residentScheduleView.apply(model: ResidenceSchedulesView.Model(
            residentScheduleView.apply(model: WidgetResidenceSchedulesView.Model(
                island: island,
                direction: direction,
                ferries: ferries

A Ferry widget/WidgetResidenceSchedulesView.swift => Ferry widget/WidgetResidenceSchedulesView.swift +130 -0
@@ 0,0 1,130 @@
//
//  ResidentSchedulesView.swift
//  Ferry widget
//
//  Created by b123400 on 2021/06/06.
//  Copyright © 2021 b123400. All rights reserved.
//

import Foundation
import UIKit

private var titleFont: UIFont = UIFontMetrics(forTextStyle: .largeTitle)
    .scaledFont(for: UIFont.monospacedDigitSystemFont(ofSize: 26, weight: .regular))

private var subheadFont: UIFont = UIFontMetrics(forTextStyle: .subheadline)
    .scaledFont(for: UIFont.monospacedDigitSystemFont(ofSize: 17, weight: .regular))

class WidgetResidenceScheduleView: UIView {
    lazy var label: UILabel = {
        let l = UILabel()
        l.font = titleFont
        return l
    }()
    lazy var subLabel: UILabel = {
        let l = UILabel()
        l.font = subheadFont
        l.textColor = UIColor.secondaryLabel
        return l
    }()
    lazy var colorView: UIView = {
        let v = UIView()
        v.layer.cornerRadius = 2.5
        return v
    }()
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
    }
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        
        self.addSubview(self.label)
        self.addSubview(self.subLabel)
        self.addSubview(self.colorView)

        label.snp.makeConstraints { (make) in
            make.top.left.bottom.equalToSuperview()
        }
        subLabel.snp.makeConstraints { (make) in
            make.left.equalTo(label.snp.right).offset(50)
            make.centerY.equalTo(label.snp.centerY)
        }
        colorView.snp.makeConstraints { (make) in
            make.top.bottom.equalTo(label)
            make.width.equalTo(5)
            make.left.equalTo(label.snp.right).offset(8)
        }
    }
}

class WidgetResidenceSchedulesView: UIView {
    
    public struct Model {
        let island: Island
        let direction: Direction
        let ferries: [Ferry<Date>]
    }
    
    lazy var label: UILabel = {
        let l = UILabel()
        l.font = titleFont
        l.adjustsFontSizeToFitWidth = true
        l.minimumScaleFactor = 0.5
        return l
    }()
    
    lazy var count: Int = 4 {
        didSet {
            rows = [0..<count].map { _ in
                WidgetResidenceScheduleView()
            }
        }
    }

    var rows = [
        WidgetResidenceScheduleView(),
        WidgetResidenceScheduleView(),
        WidgetResidenceScheduleView(),
        WidgetResidenceScheduleView()
    ]

    required init?(coder: NSCoder) {
        super.init(coder: coder)
    }
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        
        self.addSubview(label)
        label.snp.makeConstraints { make in
            make.top.right.equalToSuperview()
            make.left.equalToSuperview().offset(8)
        }
        
        let stack = UIStackView(arrangedSubviews: self.rows)
        stack.axis = .vertical
        stack.spacing = 8
        self.addSubview(stack)
        
        stack.snp.makeConstraints { make in
            make.top.equalTo(label.snp.bottom).offset(8)
            make.left.equalToSuperview().offset(8)
            make.right.equalToSuperview()
        }
    }
    
    func apply(model: Model) {
        label.text = model.island.nameForDirection(direction: model.direction)
        for i in 0..<rows.count {
            if i < model.ferries.count {
                let row = rows[i]
                let ferry = model.ferries[i]
                row.label.text = ferry.time.timeString
                row.subLabel.text = timeLeft(date: ferry.time)
                row.colorView.backgroundColor = ferry.color
            }
        }
    }
}

M FerryTimeTable3.xcodeproj/project.pbxproj => FerryTimeTable3.xcodeproj/project.pbxproj +4 -2
@@ 15,6 15,7 @@
		CF0FF14724CAEE5300CB9676 /* MainInterface.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = CF0FF14524CAEE5300CB9676 /* MainInterface.storyboard */; };
		CF0FF14B24CAEE5300CB9676 /* Ferry Timetable.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = CF0FF13E24CAEE5300CB9676 /* Ferry Timetable.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
		CF1E4A4324ACDC9300D98F41 /* LeftAlignedCollectionViewFlowLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = CF1E4A4224ACDC9300D98F41 /* LeftAlignedCollectionViewFlowLayout.swift */; };
		CF271D3D266D197D00A853C8 /* WidgetResidenceSchedulesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CF271D3C266D197D00A853C8 /* WidgetResidenceSchedulesView.swift */; };
		CF547F8324C339F9007DCF39 /* raws.json in Resources */ = {isa = PBXBuildFile; fileRef = CF547F8224C339F9007DCF39 /* raws.json */; };
		CF547F8524C33C46007DCF39 /* Schedule.swift in Sources */ = {isa = PBXBuildFile; fileRef = CF547F8424C33C46007DCF39 /* Schedule.swift */; };
		CF547F8824C359A0007DCF39 /* MenuCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = CF547F8724C359A0007DCF39 /* MenuCell.swift */; };


@@ 71,7 72,6 @@
		CFDAF408265A6312000E973A /* CoreLocation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CFDAF406265A6308000E973A /* CoreLocation.framework */; };
		CFE1044C24CAB69B00AB1B80 /* SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CFE1044B24CAB69B00AB1B80 /* SettingsView.swift */; };
		CFEF2C1424CADCCE00DA70A4 /* Json.swift in Sources */ = {isa = PBXBuildFile; fileRef = CFEF2C1324CADCCE00DA70A4 /* Json.swift */; };
		CFF0A8D0266B9304002AC7FE /* ResidenceSchedulesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CF9A58AF2663BA67003FDFFA /* ResidenceSchedulesView.swift */; };
		FD342830DA4812F7F903F66C /* Pods_FerryTimetable3.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F085409AD139E84060EF67C8 /* Pods_FerryTimetable3.framework */; };
/* End PBXBuildFile section */



@@ 130,6 130,7 @@
		CF0FF14624CAEE5300CB9676 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/MainInterface.storyboard; sourceTree = "<group>"; };
		CF0FF14824CAEE5300CB9676 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
		CF1E4A4224ACDC9300D98F41 /* LeftAlignedCollectionViewFlowLayout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LeftAlignedCollectionViewFlowLayout.swift; sourceTree = "<group>"; };
		CF271D3C266D197D00A853C8 /* WidgetResidenceSchedulesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WidgetResidenceSchedulesView.swift; sourceTree = "<group>"; };
		CF547F8224C339F9007DCF39 /* raws.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = raws.json; sourceTree = "<group>"; };
		CF547F8424C33C46007DCF39 /* Schedule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Schedule.swift; sourceTree = "<group>"; };
		CF547F8724C359A0007DCF39 /* MenuCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MenuCell.swift; sourceTree = "<group>"; };


@@ 273,6 274,7 @@
				CFC73E6424D8369B00CA4F41 /* InfoPlist.strings */,
				CFC73E5E24D8336E00CA4F41 /* Localizable.strings */,
				CF5A5ADE24CB033000DDF6BB /* WidgetView.swift */,
				CF271D3C266D197D00A853C8 /* WidgetResidenceSchedulesView.swift */,
			);
			path = "Ferry widget";
			sourceTree = "<group>";


@@ 722,7 724,7 @@
				CF5A5AD424CAFA2500DDF6BB /* MenuCell.swift in Sources */,
				CF5A5AD724CAFA8900DDF6BB /* Timetable.swift in Sources */,
				CF5A5AE424CB757300DDF6BB /* CurrentScheduleView.swift in Sources */,
				CFF0A8D0266B9304002AC7FE /* ResidenceSchedulesView.swift in Sources */,
				CF271D3D266D197D00A853C8 /* WidgetResidenceSchedulesView.swift in Sources */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};