Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
26 changes: 7 additions & 19 deletions src/front/macOS/kDrive.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -58,35 +58,23 @@
F9A9A0562E61A887005FA196 /* Exceptions for "kDriveCoreUI" folder in "kDrive" target */ = {
isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
membershipExceptions = (
Utils/ColoredMenuItem.swift,
Views/BadgeButton.swift,
Views/ClickableOutlineView.swift,
Views/ColoredPopUpButton.swift,
Views/ColoredPopUpButtonCell.swift,
Views/SidebarHeaderView.swift,
Views/SidebarTableCellView.swift,
);
target = 37A1C4252E546A5200596DBB /* kDrive */;
};
F9A9A0572E61A887005FA196 /* Exceptions for "kDriveCoreUI" folder in "kDriveCoreUI" target */ = {
F9ACC5322E5DCC780081E80B /* Exceptions for "kDrive" folder in "kDrive" target */ = {
isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
membershipExceptions = (
Utils/ColoredMenuItem.swift,
Views/BadgeButton.swift,
Views/ClickableOutlineView.swift,
Views/ColoredPopUpButton.swift,
Views/ColoredPopUpButtonCell.swift,
Views/SidebarHeaderView.swift,
Views/SidebarTableCellView.swift,
Resources/Info.plist,
);
target = 37A1C43E2E546A9600596DBB /* kDriveCoreUI */;
target = 37A1C4252E546A5200596DBB /* kDrive */;
};
F9ACC5322E5DCC780081E80B /* Exceptions for "kDrive" folder in "kDrive" target */ = {
F9C97F782E86DFB600C01B85 /* Exceptions for "kDriveCoreUI" folder in "kDriveCoreUI" target */ = {
isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
membershipExceptions = (
Resources/Info.plist,
Views/SidebarHeaderView.swift,
);
target = 37A1C4252E546A5200596DBB /* kDrive */;
target = 37A1C43E2E546A9600596DBB /* kDriveCoreUI */;
};
/* End PBXFileSystemSynchronizedBuildFileExceptionSet section */

Expand All @@ -103,7 +91,7 @@
isa = PBXFileSystemSynchronizedRootGroup;
exceptions = (
F9A9A0562E61A887005FA196 /* Exceptions for "kDriveCoreUI" folder in "kDrive" target */,
F9A9A0572E61A887005FA196 /* Exceptions for "kDriveCoreUI" folder in "kDriveCoreUI" target */,
F9C97F782E86DFB600C01B85 /* Exceptions for "kDriveCoreUI" folder in "kDriveCoreUI" target */,
);
path = kDriveCoreUI;
sourceTree = "<group>";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,11 @@ final class MainSidebarViewController: NSViewController {
scrollView.topAnchor.constraint(equalTo: popUpButton.bottomAnchor, constant: 16),
scrollView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor),
scrollView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor),
scrollView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor)
scrollView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor),

outlineView.topAnchor.constraint(equalTo: scrollView.contentView.topAnchor),
outlineView.leadingAnchor.constraint(equalTo: scrollView.contentView.leadingAnchor),
outlineView.trailingAnchor.constraint(equalTo: scrollView.contentView.trailingAnchor)
])
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,41 @@
import Cocoa
import kDriveCoreUI

class GeneralPreferencesViewController: TitledViewController {
class GeneralPreferencesViewController: InsetGroupedPreferencesPaneController {
convenience init() {
self.init(toolbarTitle: SidebarItem.general.title)
}

override func viewDidLoad() {
super.viewDidLoad()
setupSection()
}

private func setupSection() {
let automaticUpdateLabel = NSTextField(labelWithString: "Mises à jour automatiques")
let automaticUpdateSwitch = NSSwitch()

let languageLabel = NSTextField(labelWithString: "Langue")
let languagePopUpButton = NSPopUpButton()

let startAtLoginLabel = NSTextField(labelWithString: "Ouvrir kDrive au démarrage de l’ordinateur")
let startAtLoginSwitch = NSSwitch()

let aboutLabel = NSTextField(labelWithString: "À propos de kDrive")
let aboutButton = NSButton()
aboutButton.bezelStyle = .helpButton
aboutButton.controlSize = .small

insertNewGroupedSection(with: [
[automaticUpdateLabel, automaticUpdateSwitch],
[languageLabel, languagePopUpButton],
[startAtLoginLabel, startAtLoginSwitch],
[aboutLabel, aboutButton]
])
}
}

@available(macOS 14, *)
#Preview {
GeneralPreferencesViewController()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
Infomaniak kDrive - Desktop
Copyright (C) 2023-2025 Infomaniak Network SA

This program 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
(at your option) any later version.

This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/

import Cocoa

public final class NSSeparator: NSBox {
public override init(frame: NSRect) {
super.init(frame: frame)
boxType = .separator
}

public required init?(coder: NSCoder) {
super.init(coder: coder)
boxType = .separator
}

public convenience init() {
self.init(frame: .zero)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
Infomaniak kDrive - Desktop
Copyright (C) 2023-2025 Infomaniak Network SA

This program 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
(at your option) any later version.

This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/

import Cocoa

protocol InsetGroupedPreferencesPaneDataSource: AnyObject {

}

open class InsetGroupedPreferencesPaneController: PreferencesPaneController {



}
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
/*
Infomaniak kDrive - Desktop
Copyright (C) 2023-2025 Infomaniak Network SA

This program 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
(at your option) any later version.

This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/

import Cocoa
import kDriveCoreUI

open class PreferencesPaneController: TitledViewController {
var scrollView: NSScrollView!
var stackView: NSStackView!

open override func viewDidLoad() {
super.viewDidLoad()
setupStackViewWithinScrollView()
}

public func insertNewGroupedSection(title: String? = nil, with rows: [[NSView]]) {
let box = createContainerBox(title: title)

let rowsWithDividers = insertDividersIntoArray(rows)

let gridView = NSGridView(views: rowsWithDividers)
box.contentView = gridView

gridView.translatesAutoresizingMaskIntoConstraints = false
gridView.yPlacement = .center
gridView.columnSpacing = 16
gridView.rowSpacing = 0
gridView.column(at: 0).xPlacement = .leading
gridView.column(at: 1).xPlacement = .trailing

configureCells(of: gridView)

NSLayoutConstraint.activate([
gridView.topAnchor.constraint(equalTo: box.topAnchor),
gridView.leadingAnchor.constraint(equalTo: box.leadingAnchor, constant: 10),
gridView.trailingAnchor.constraint(equalTo: box.trailingAnchor, constant: -10),
gridView.bottomAnchor.constraint(equalTo: box.bottomAnchor)
])

stackView.addView(box, in: .bottom)
}

private func setupStackViewWithinScrollView() {
scrollView = NSScrollView()
scrollView.translatesAutoresizingMaskIntoConstraints = false
scrollView.hasVerticalScroller = true
scrollView.autohidesScrollers = true
scrollView.drawsBackground = false
scrollView.contentView = FlippedClipView()
view.addSubview(scrollView)

stackView = NSStackView()
stackView.translatesAutoresizingMaskIntoConstraints = false
stackView.orientation = .vertical
stackView.edgeInsets = NSEdgeInsets(top: 0, left: 20, bottom: 20, right: 20)
stackView.spacing = 10
scrollView.documentView = stackView

NSLayoutConstraint.activate([
scrollView.topAnchor.constraint(equalTo: view.topAnchor),
scrollView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor),
scrollView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor),
scrollView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor),

stackView.topAnchor.constraint(equalTo: scrollView.contentView.topAnchor),
stackView.leadingAnchor.constraint(equalTo: scrollView.contentView.leadingAnchor),
stackView.trailingAnchor.constraint(equalTo: scrollView.contentView.trailingAnchor)
])
}

private func configureCells(of grid: NSGridView) {
let numberOfRows = grid.numberOfRows
for rowIndex in 0..<numberOfRows {
let row = grid.row(at: rowIndex)

if row.cell(at: 0).contentView is NSSeparator {
row.mergeCells(in: NSRange(location: 0, length: row.numberOfCells))
} else {
row.height = 42
}
}
}

private func insertDividersIntoArray(_ rows: [[NSView]]) -> [[NSView]] {
var grid = [[NSView]]()
for row in rows {
grid.append(row)

if row != rows.last {
grid.append([NSSeparator()])
}
}

return grid
}

private func createContainerBox(title: String?) -> NSBox {
let box = NSBox()
box.translatesAutoresizingMaskIntoConstraints = false
if let title {
box.title = title
} else {
box.titlePosition = .noTitle
}

return box
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,11 @@ class PreferencesSidebarViewController: NSViewController {
scrollView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
scrollView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor),
scrollView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor),
scrollView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor)
scrollView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor),

outlineView.topAnchor.constraint(equalTo: scrollView.contentView.topAnchor),
outlineView.leadingAnchor.constraint(equalTo: scrollView.contentView.leadingAnchor),
outlineView.trailingAnchor.constraint(equalTo: scrollView.contentView.trailingAnchor)
])
}
}
Expand Down
8 changes: 4 additions & 4 deletions src/front/macOS/kDriveCoreUI/Views/BadgeButton.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,18 @@

import Cocoa

final class BadgeButton: NSButton {
init() {
public final class BadgeButton: NSButton {
public init() {
super.init(frame: .zero)
bezelStyle = .badge
}

@available(*, unavailable)
required init?(coder: NSCoder) {
public required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

override func hitTest(_ point: NSPoint) -> NSView? {
override public func hitTest(_ point: NSPoint) -> NSView? {
return nil
}
}
10 changes: 5 additions & 5 deletions src/front/macOS/kDriveCoreUI/Views/ClickableOutlineView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,16 @@

import Cocoa

protocol ClickableOutlineViewDelegate: NSOutlineViewDelegate {
public protocol ClickableOutlineViewDelegate: NSOutlineViewDelegate {
func outlineView(_ outlineView: NSOutlineView, didClick item: Any?)
}

final class ClickableOutlineView: NSOutlineView {
public final class ClickableOutlineView: NSOutlineView {
private static let menuTopPadding: CGFloat = 4.0

private(set) var activatedRowIndexes = IndexSet()

override func mouseDown(with event: NSEvent) {
override public func mouseDown(with event: NSEvent) {
super.mouseDown(with: event)

guard window?.isKeyWindow == true else { return }
Expand All @@ -36,7 +36,7 @@ final class ClickableOutlineView: NSOutlineView {
}
}

override func rowView(atRow row: Int, makeIfNecessary: Bool) -> NSTableRowView? {
override public func rowView(atRow row: Int, makeIfNecessary: Bool) -> NSTableRowView? {
let tableRow = super.rowView(atRow: row, makeIfNecessary: makeIfNecessary)
if let tableRow, makeIfNecessary {
markRowAsActivated(tableRow, isActivated: activatedRowIndexes.contains(row))
Expand All @@ -45,7 +45,7 @@ final class ClickableOutlineView: NSOutlineView {
return tableRow
}

func showMenu(_ menu: NSMenu, at item: Any) {
public func showMenu(_ menu: NSMenu, at item: Any) {
let itemRow = row(forItem: item)
guard itemRow != -1 else { return }

Expand Down
9 changes: 5 additions & 4 deletions src/front/macOS/kDriveCoreUI/Views/ColoredPopUpButton.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,18 @@

import Cocoa

final class ColoredPopUpButton: NSPopUpButton {
init() {
public final class ColoredPopUpButton: NSPopUpButton {
public init() {
super.init(frame: .zero, pullsDown: false)
cell = ColoredPopUpButtonCell()
}

required init?(coder: NSCoder) {
@available(*, unavailable)
public required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

func addItem(withTitle title: String, image: NSImage, color: NSColor) {
public func addItem(withTitle title: String, image: NSImage, color: NSColor) {
menu?.addItem(ColoredMenuItem(title: title, image: image, color: color))
}
}
Loading
Loading