Added Shortcuts feature to the side menu, read from the config

This commit is contained in:
QuentinArguillere 2024-11-19 14:48:42 +01:00
parent 60d006248b
commit 17e7c05576
9 changed files with 182 additions and 1 deletions

View file

@ -27,6 +27,8 @@
66C491FD2B24D36500CEA16D /* AudioRouteUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66C491FC2B24D36500CEA16D /* AudioRouteUtils.swift */; };
66C491FF2B24D4AC00CEA16D /* FileUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66C491FE2B24D4AC00CEA16D /* FileUtils.swift */; };
66C492012B24DB6900CEA16D /* Log.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66C492002B24DB6900CEA16D /* Log.swift */; };
66CD1E602CEBA19F00898718 /* SideMenuShortcut.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66CD1E5F2CEBA19B00898718 /* SideMenuShortcut.swift */; };
66D382052CEB7E0A0063E1C5 /* ShortcutModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66D382042CEB7E050063E1C5 /* ShortcutModel.swift */; };
66E50A492BD12B2300AD61CA /* MeetingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66E50A482BD12B2300AD61CA /* MeetingsView.swift */; };
66E50A4B2BD12B7800AD61CA /* MeetingsFragment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66E50A4A2BD12B7800AD61CA /* MeetingsFragment.swift */; };
66E56BC92BA4A6D7006CE56F /* MeetingsListViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66E56BC82BA4A6D7006CE56F /* MeetingsListViewModel.swift */; };
@ -220,6 +222,8 @@
66C491FC2B24D36500CEA16D /* AudioRouteUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioRouteUtils.swift; sourceTree = "<group>"; };
66C491FE2B24D4AC00CEA16D /* FileUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileUtils.swift; sourceTree = "<group>"; };
66C492002B24DB6900CEA16D /* Log.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Log.swift; sourceTree = "<group>"; };
66CD1E5F2CEBA19B00898718 /* SideMenuShortcut.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SideMenuShortcut.swift; sourceTree = "<group>"; };
66D382042CEB7E050063E1C5 /* ShortcutModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShortcutModel.swift; sourceTree = "<group>"; };
66E50A482BD12B2300AD61CA /* MeetingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MeetingsView.swift; sourceTree = "<group>"; };
66E50A4A2BD12B7800AD61CA /* MeetingsFragment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MeetingsFragment.swift; sourceTree = "<group>"; };
66E56BC82BA4A6D7006CE56F /* MeetingsListViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MeetingsListViewModel.swift; sourceTree = "<group>"; };
@ -427,6 +431,14 @@
path = Extensions;
sourceTree = "<group>";
};
66D382032CEB7DB80063E1C5 /* Models */ = {
isa = PBXGroup;
children = (
66D382042CEB7E050063E1C5 /* ShortcutModel.swift */,
);
path = Models;
sourceTree = "<group>";
};
66E56BC52BA45E49006CE56F /* Meetings */ = {
isa = PBXGroup;
children = (
@ -589,6 +601,7 @@
D74C9CFD2ACAEC150021626A /* Fragments */,
D7A03FBE2ACC2E010081A588 /* History */,
66E56BC52BA45E49006CE56F /* Meetings */,
66D382032CEB7DB80063E1C5 /* Models */,
D7A2EDD42AC180FE005D90FC /* Viewmodel */,
D719ABB82ABC67BF00B41C10 /* ContentView.swift */,
);
@ -688,6 +701,7 @@
C62817332C1C7C7400DBA646 /* HelpView.swift */,
C6DC4E3E2C19C289009096FD /* SideMenuEntry.swift */,
C62817272C1B389700DBA646 /* SideMenuAccountRow.swift */,
66CD1E5F2CEBA19B00898718 /* SideMenuShortcut.swift */,
D7E6D04C2AEBD77600A57AAF /* CustomBottomSheet.swift */,
D7E2E69E2CE356C90080DA0D /* PopupViewWithTextField.swift */,
);
@ -1105,6 +1119,7 @@
D71FCA832AE14D6E00D2E43E /* ContactFragment.swift in Sources */,
D7C3650C2AF0084000FE6142 /* EditContactViewModel.swift in Sources */,
D78E062A2BEA698E00CE3783 /* MediaEncryptedSheetBottomSheet.swift in Sources */,
66CD1E602CEBA19F00898718 /* SideMenuShortcut.swift in Sources */,
D7B5678E2B28888F00DE63EB /* CallView.swift in Sources */,
D71A0E192B485ADF0002C6CD /* ViewExtension.swift in Sources */,
D759CB642C3FBD4200AC35E8 /* StartConversationFragment.swift in Sources */,
@ -1220,6 +1235,7 @@
D714DE602C1B3B34006C1F1D /* RegisterViewModel.swift in Sources */,
D70C82A72C85F5910087F43F /* ConversationForwardMessageViewModel.swift in Sources */,
D74DA0122C047F0700A8561D /* HistoryModel.swift in Sources */,
66D382052CEB7E0A0063E1C5 /* ShortcutModel.swift in Sources */,
D72250692ADFBF2D008FB426 /* SideMenu.swift in Sources */,
C6DC4E3F2C19C289009096FD /* SideMenuEntry.swift in Sources */,
D714DE622C1C4636006C1F1D /* RegisterCodeConfirmationFragment.swift in Sources */,

View file

@ -0,0 +1,21 @@
{
"images" : [
{
"filename" : "arrow-square-out.svg",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M224,104a8,8,0,0,1-16,0V59.32l-66.33,66.34a8,8,0,0,1-11.32-11.32L196.68,48H152a8,8,0,0,1,0-16h64a8,8,0,0,1,8,8Zm-40,24a8,8,0,0,0-8,8v72H48V80h72a8,8,0,0,0,0-16H48A16,16,0,0,0,32,80V208a16,16,0,0,0,16,16H176a16,16,0,0,0,16-16V136A8,8,0,0,0,184,128Z"></path></svg>

After

Width:  |  Height:  |  Size: 371 B

View file

@ -0,0 +1,21 @@
{
"images" : [
{
"filename" : "link-break.svg",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256"><rect width="256" height="256" fill="none"/><path d="M192,120l12.28-11.72a40,40,0,0,0-56.56-56.56L136,64" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><path d="M64,136,51.72,147.72a40,40,0,0,0,56.56,56.56L120,192" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><line x1="192" y1="160" x2="216" y2="160" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><line x1="40" y1="96" x2="64" y2="96" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><line x1="160" y1="192" x2="160" y2="216" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><line x1="96" y1="40" x2="96" y2="64" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/></svg>

After

Width:  |  Height:  |  Size: 997 B

View file

@ -42,7 +42,7 @@ final class CoreContext: ObservableObject {
@Published var coreIsStarted: Bool = false
@Published var accounts: [AccountModel] = []
@Published var enteredForeground = false
@Published var shortcuts: [ShortcutModel] = []
private var mCore: Core!
private var mIterateSuscription: AnyCancellable?
@ -148,6 +148,33 @@ final class CoreContext: ObservableObject {
self.mCore.config!.setBool(section: "sip", key: "auto_answer_replacing_calls", value: false)
self.mCore.config!.setBool(section: "sip", key: "deliver_imdn", value: false)
let shortcutsCount = self.mCore.config!.getInt(section: "ui", key: "shortcut_count", defaultValue: 0)
if shortcutsCount > 0 {
var shortcuts: [ShortcutModel] = []
for i in 0...shortcutsCount {
let shortcutSection = "shortcut_\(i)"
let link = self.mCore.config!.getString(section: shortcutSection, key: "link", defaultString: "")
let linkUrl = URL(string: link)
let name = self.mCore.config!.getString(section: shortcutSection, key: "name", defaultString: "")
let iconLink = self.mCore.config!.getString(section: shortcutSection, key: "icon", defaultString: "")
let iconLinkUrl = URL(string: iconLink)
if linkUrl == nil {
Log.error("Could not add shortcut #\(i) pointing to \(name) because the link URL '\(link)' is invalid")
continue
}
if iconLinkUrl == nil {
Log.error("Could not add shortcut #\(i) pointing to \(name) because the icon link URL '\(iconLink)' is invalid")
continue
}
shortcuts.append(ShortcutModel(linkUrl: linkUrl!, name: name, iconLinkUrl: iconLinkUrl!))
}
DispatchQueue.main.async {
self.shortcuts = shortcuts
}
}
self.mCoreDelegate = CoreDelegateStub(onGlobalStateChanged: { (core: Core, state: GlobalState, _: String) in
if state == GlobalState.On {
#if DEBUG

View file

@ -118,6 +118,9 @@ struct SideMenu: View {
.frame(height: 1)
VStack(spacing: 19) {
ForEach(0..<CoreContext.shared.shortcuts.count, id: \.self) { index in
SideMenuShortcut(shortcutModel: CoreContext.shared.shortcuts[index])
}
SideMenuEntry(
iconName: "gear",
title: "settings_title"

View file

@ -0,0 +1,59 @@
/*
* Copyright (c) 2010-2024 Belledonne Communications SARL.
*
* This file is part of linphone-iphone
*
* 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 SwiftUI
struct SideMenuShortcut: View {
@ObservedObject var shortcutModel: ShortcutModel
var body: some View {
Link(destination: shortcutModel.linkUrl) {
HStack {
AsyncImage(url: shortcutModel.iconLinkUrl) { phase in
if let image = phase.image {
image
.resizable()
.aspectRatio(contentMode: .fit)
} else if phase.error != nil {
Image("link-break")
.renderingMode(.template)
.resizable()
} else {
ProgressView()
}
}
.frame(width: 20, height: 20)
Text(NSLocalizedString(shortcutModel.name, comment: shortcutModel.name))
.default_text_style_600(styleSize: 13)
.padding(.leading, 4)
Spacer()
Image("arrow-square-out")
.renderingMode(.template)
.resizable()
.foregroundStyle(Color.grayMain2c600)
.frame(width: 20, height: 20)
}
.background()
}
}
}
#Preview {
SideMenuShortcut(shortcutModel: ShortcutModel(linkUrl: URL("link")!, name: "name", iconLinkUrl: URL("icon")!)
)
}

View file

@ -0,0 +1,32 @@
/*
* Copyright (c) 2010-2024 Belledonne Communications SARL.
*
* This file is part of linphone-iphone
*
* 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 Foundation
class ShortcutModel: ObservableObject {
@Published var linkUrl: URL
@Published var name: String
@Published var iconLinkUrl: URL
init(linkUrl: URL, name: String, iconLinkUrl: URL) {
self.linkUrl = linkUrl
self.name = name
self.iconLinkUrl = iconLinkUrl
}
}