forked from mirrors/linphone-iphone
Add presence icon for Avatar
This commit is contained in:
parent
ada6065b21
commit
5cf66f2853
16 changed files with 343 additions and 89 deletions
|
|
@ -29,6 +29,8 @@
|
|||
D72343362AD037AF009AA24E /* ToastView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D72343352AD037AF009AA24E /* ToastView.swift */; };
|
||||
D72992392ADD7F68003AF125 /* HistoryContactFragment.swift in Sources */ = {isa = PBXBuildFile; fileRef = D72992382ADD7F68003AF125 /* HistoryContactFragment.swift */; };
|
||||
D732A9092AFD235500DB42BA /* ShareSheetController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D732A9082AFD235500DB42BA /* ShareSheetController.swift */; };
|
||||
D732A90C2B0376F500DB42BA /* linphonerc-default in Resources */ = {isa = PBXBuildFile; fileRef = D732A90A2B0376F500DB42BA /* linphonerc-default */; };
|
||||
D732A90D2B0376F500DB42BA /* linphonerc-factory in Resources */ = {isa = PBXBuildFile; fileRef = D732A90B2B0376F500DB42BA /* linphonerc-factory */; };
|
||||
D748BF2C2ACD82D2004844EB /* ThirdPartySipAccountLoginFragment.swift in Sources */ = {isa = PBXBuildFile; fileRef = D748BF2B2ACD82D2004844EB /* ThirdPartySipAccountLoginFragment.swift */; };
|
||||
D748BF2E2ACD82E7004844EB /* ThirdPartySipAccountWarningFragment.swift in Sources */ = {isa = PBXBuildFile; fileRef = D748BF2D2ACD82E7004844EB /* ThirdPartySipAccountWarningFragment.swift */; };
|
||||
D74C9CF82ACACECE0021626A /* WelcomePage1Fragment.swift in Sources */ = {isa = PBXBuildFile; fileRef = D74C9CF72ACACECE0021626A /* WelcomePage1Fragment.swift */; };
|
||||
|
|
@ -45,6 +47,7 @@
|
|||
D7A03FC02ACC2E390081A588 /* HistoryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7A03FBF2ACC2E390081A588 /* HistoryView.swift */; };
|
||||
D7A03FC62ACC458A0081A588 /* SplashScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7A03FC52ACC458A0081A588 /* SplashScreen.swift */; };
|
||||
D7A2EDD62AC18115005D90FC /* SharedMainViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7A2EDD52AC18115005D90FC /* SharedMainViewModel.swift */; };
|
||||
D7ADF6002AFE356400212231 /* Avatar.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7ADF5FF2AFE356400212231 /* Avatar.swift */; };
|
||||
D7B5066D2AEFA9B900CEB4E9 /* ContactInnerFragment.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7B5066C2AEFA9B900CEB4E9 /* ContactInnerFragment.swift */; };
|
||||
D7C365082AEFAB7F00FE6142 /* ContactListBottomSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7C365072AEFAB7F00FE6142 /* ContactListBottomSheet.swift */; };
|
||||
D7C3650A2AF001C300FE6142 /* EditContactFragment.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7C365092AF001C300FE6142 /* EditContactFragment.swift */; };
|
||||
|
|
@ -95,6 +98,8 @@
|
|||
D72343352AD037AF009AA24E /* ToastView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToastView.swift; sourceTree = "<group>"; };
|
||||
D72992382ADD7F68003AF125 /* HistoryContactFragment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HistoryContactFragment.swift; sourceTree = "<group>"; };
|
||||
D732A9082AFD235500DB42BA /* ShareSheetController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareSheetController.swift; sourceTree = "<group>"; };
|
||||
D732A90A2B0376F500DB42BA /* linphonerc-default */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "linphonerc-default"; sourceTree = "<group>"; };
|
||||
D732A90B2B0376F500DB42BA /* linphonerc-factory */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "linphonerc-factory"; sourceTree = "<group>"; };
|
||||
D748BF2B2ACD82D2004844EB /* ThirdPartySipAccountLoginFragment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThirdPartySipAccountLoginFragment.swift; sourceTree = "<group>"; };
|
||||
D748BF2D2ACD82E7004844EB /* ThirdPartySipAccountWarningFragment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThirdPartySipAccountWarningFragment.swift; sourceTree = "<group>"; };
|
||||
D74C9CF72ACACECE0021626A /* WelcomePage1Fragment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WelcomePage1Fragment.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -112,6 +117,7 @@
|
|||
D7A03FC52ACC458A0081A588 /* SplashScreen.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SplashScreen.swift; sourceTree = "<group>"; };
|
||||
D7A2EDD52AC18115005D90FC /* SharedMainViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SharedMainViewModel.swift; sourceTree = "<group>"; };
|
||||
D7A2EDDA2AC19EEC005D90FC /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
|
||||
D7ADF5FF2AFE356400212231 /* Avatar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Avatar.swift; sourceTree = "<group>"; };
|
||||
D7B5066C2AEFA9B900CEB4E9 /* ContactInnerFragment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactInnerFragment.swift; sourceTree = "<group>"; };
|
||||
D7C365072AEFAB7F00FE6142 /* ContactListBottomSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactListBottomSheet.swift; sourceTree = "<group>"; };
|
||||
D7C365092AF001C300FE6142 /* EditContactFragment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditContactFragment.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -165,6 +171,7 @@
|
|||
D7C3650D2AF15BF200FE6142 /* PhotoPicker.swift */,
|
||||
D7C48DF32AFA66F900D938CB /* EditContactController.swift */,
|
||||
D732A9082AFD235500DB42BA /* ShareSheetController.swift */,
|
||||
D7ADF5FF2AFE356400212231 /* Avatar.swift */,
|
||||
);
|
||||
path = Utils;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -201,6 +208,7 @@
|
|||
D70C93DD2AC2D0F60063CA3B /* Localizable.xcstrings */,
|
||||
D719ABBD2ABC67BF00B41C10 /* Preview Content */,
|
||||
D7D24D0C2AC1B4C700C6F35B /* Fonts */,
|
||||
D7ADF6012AFE5C7C00212231 /* Ressources */,
|
||||
);
|
||||
path = Linphone;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -375,6 +383,15 @@
|
|||
path = Viewmodel;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D7ADF6012AFE5C7C00212231 /* Ressources */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D732A90A2B0376F500DB42BA /* linphonerc-default */,
|
||||
D732A90B2B0376F500DB42BA /* linphonerc-factory */,
|
||||
);
|
||||
path = Ressources;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D7D24D0C2AC1B4C700C6F35B /* Fonts */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
|
@ -469,6 +486,8 @@
|
|||
D719ABBF2ABC67BF00B41C10 /* Preview Assets.xcassets in Resources */,
|
||||
D719ABBB2ABC67BF00B41C10 /* Assets.xcassets in Resources */,
|
||||
D7D24D132AC1B4E800C6F35B /* NotoSans-Medium.ttf in Resources */,
|
||||
D732A90C2B0376F500DB42BA /* linphonerc-default in Resources */,
|
||||
D732A90D2B0376F500DB42BA /* linphonerc-factory in Resources */,
|
||||
D70C93DE2AC2D0F60063CA3B /* Localizable.xcstrings in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
|
|
@ -503,6 +522,7 @@
|
|||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D7C3650E2AF15BF200FE6142 /* PhotoPicker.swift in Sources */,
|
||||
D7ADF6002AFE356400212231 /* Avatar.swift in Sources */,
|
||||
D71707202AC5989C0037746F /* TextExtension.swift in Sources */,
|
||||
D719ABB92ABC67BF00B41C10 /* ContentView.swift in Sources */,
|
||||
D71FCA832AE14D6E00D2E43E /* ContactFragment.swift in Sources */,
|
||||
|
|
|
|||
21
Linphone/Assets.xcassets/presence-busy.imageset/Contents.json
vendored
Normal file
21
Linphone/Assets.xcassets/presence-busy.imageset/Contents.json
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "presence-busy.svg",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
5
Linphone/Assets.xcassets/presence-busy.imageset/presence-busy.svg
vendored
Normal file
5
Linphone/Assets.xcassets/presence-busy.imageset/presence-busy.svg
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
<svg width="23" height="23" viewBox="0 0 23 23" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g id="Pastille de présence">
|
||||
<circle id="Ellipse 2" cx="11.7222" cy="11.8889" r="10.1111" fill="#DBB820" stroke="white" stroke-width="2"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 259 B |
21
Linphone/Assets.xcassets/presence-online.imageset/Contents.json
vendored
Normal file
21
Linphone/Assets.xcassets/presence-online.imageset/Contents.json
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "presence-online.svg",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
5
Linphone/Assets.xcassets/presence-online.imageset/presence-online.svg
vendored
Normal file
5
Linphone/Assets.xcassets/presence-online.imageset/presence-online.svg
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
<svg width="23" height="23" viewBox="0 0 23 23" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g id="Pastille de présence">
|
||||
<circle id="Ellipse 2" cx="11.7224" cy="11.8889" r="10.1111" fill="#4FAE80" stroke="white" stroke-width="2"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 259 B |
|
|
@ -30,6 +30,7 @@ final class CoreContext: ObservableObject {
|
|||
@Published var loggingInProgress: Bool = false
|
||||
@Published var toastMessage: String = ""
|
||||
@Published var defaultAccount: Account?
|
||||
@Published var coreIsStarted: Bool = false
|
||||
|
||||
private var mCore: Core!
|
||||
private var mIteratePublisher: AnyCancellable?
|
||||
|
|
@ -53,17 +54,39 @@ final class CoreContext: ObservableObject {
|
|||
|
||||
coreQueue.async {
|
||||
let configDir = Factory.Instance.getConfigDir(context: nil)
|
||||
try? self.mCore = Factory.Instance.createCore(configPath: "\(configDir)/MyConfig", factoryConfigPath: "", systemContext: nil)
|
||||
|
||||
let url = NSURL(fileURLWithPath: configDir)
|
||||
if let pathComponent = url.appendingPathComponent("linphonerc") {
|
||||
let filePath = pathComponent.path
|
||||
let fileManager = FileManager.default
|
||||
if !fileManager.fileExists(atPath: filePath) {
|
||||
let path = Bundle.main.path(forResource: "linphonerc-default", ofType: nil)
|
||||
if path != nil {
|
||||
try? FileManager.default.copyItem(at: NSURL(fileURLWithPath: path!) as URL, to: pathComponent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let config: Config! = Config.newForSharedCore(
|
||||
appGroupId: "group.org.linphone.phone.msgNotification",
|
||||
configFilename: "linphonerc",
|
||||
factoryConfigFilename: Bundle.main.path(forResource: "linphonerc-factory", ofType: nil)
|
||||
)
|
||||
|
||||
self.mCore = try? Factory.Instance.createCoreWithConfig(config: config, systemContext: nil)
|
||||
|
||||
self.mCore.autoIterateEnabled = false
|
||||
self.mCore.friendsDatabasePath = "\(configDir)/friends.db"
|
||||
|
||||
self.mCore.publisher?.onGlobalStateChanged?.postOnMainQueue { (cbVal: (core: Core, state: GlobalState, message: String)) in
|
||||
if cbVal.state == GlobalState.On {
|
||||
self.defaultAccount = self.mCore.defaultAccount
|
||||
self.coreIsStarted = true
|
||||
} else if cbVal.state == GlobalState.Off {
|
||||
self.defaultAccount = nil
|
||||
}
|
||||
}
|
||||
|
||||
try? self.mCore.start()
|
||||
|
||||
// Create a Core listener to listen for the callback we need
|
||||
|
|
|
|||
|
|
@ -2,9 +2,15 @@
|
|||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.security.app-sandbox</key>
|
||||
<true/>
|
||||
<key>com.apple.security.files.user-selected.read-only</key>
|
||||
<true/>
|
||||
<key>com.apple.security.app-sandbox</key>
|
||||
<true/>
|
||||
<key>com.apple.security.application-groups</key>
|
||||
<array>
|
||||
<string>group.belledonne-communications.linphone</string>
|
||||
<string>group.org.linphone.phone.msgNotification</string>
|
||||
<string>group.org.linphone.phone.linphoneExtension</string>
|
||||
</array>
|
||||
<key>com.apple.security.files.user-selected.read-only</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ struct LinphoneApp: App {
|
|||
|
||||
var body: some Scene {
|
||||
WindowGroup {
|
||||
if isActive {
|
||||
if isActive && coreContext.coreIsStarted {
|
||||
if !sharedMainViewModel.welcomeViewDisplayed {
|
||||
WelcomeView(sharedMainViewModel: sharedMainViewModel)
|
||||
} else if coreContext.defaultAccount == nil || sharedMainViewModel.displayProfileMode {
|
||||
|
|
|
|||
39
Linphone/Ressources/linphonerc-default
Normal file
39
Linphone/Ressources/linphonerc-default
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
|
||||
## Start of default rc
|
||||
|
||||
[sip]
|
||||
contact="Linphone iPhone" <sip:linphone.iphone@unknown-host>
|
||||
use_info=0
|
||||
use_ipv6=1
|
||||
keepalive_period=30000
|
||||
sip_port=-1
|
||||
sip_tcp_port=-1
|
||||
sip_tls_port=-1
|
||||
media_encryption=none
|
||||
update_presence_model_timestamp_before_publish_expires_refresh=1
|
||||
|
||||
[net]
|
||||
#Because dynamic bitrate adaption can increase bitrate, we must allow "no limit"
|
||||
download_bw=0
|
||||
upload_bw=0
|
||||
|
||||
[video]
|
||||
size=vga
|
||||
|
||||
[app]
|
||||
tunnel=disabled
|
||||
auto_start=1
|
||||
record_aware=1
|
||||
|
||||
[tunnel]
|
||||
host=
|
||||
port=443
|
||||
|
||||
[misc]
|
||||
log_collection_upload_server_url=https://www.linphone.org:444/lft.php
|
||||
file_transfer_server_url=https://www.linphone.org:444/lft.php
|
||||
version_check_url_root=https://www.linphone.org/releases
|
||||
max_calls=10
|
||||
conference_layout=1
|
||||
|
||||
## End of default rc
|
||||
65
Linphone/Ressources/linphonerc-factory
Normal file
65
Linphone/Ressources/linphonerc-factory
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
|
||||
## Start of factory rc
|
||||
|
||||
# This file shall not contain path referencing package name, in order to be portable when app is renamed.
|
||||
# Paths to resources must be set from LinphoneManager, after creating LinphoneCore.
|
||||
|
||||
[net]
|
||||
mtu=1300
|
||||
force_ice_disablement=0
|
||||
|
||||
[rtp]
|
||||
accept_any_encryption=1
|
||||
|
||||
[sip]
|
||||
guess_hostname=1
|
||||
register_only_when_network_is_up=1
|
||||
auto_net_state_mon=1
|
||||
auto_answer_replacing_calls=1
|
||||
ping_with_options=0
|
||||
use_cpim=1
|
||||
zrtp_key_agreements_suites=MS_ZRTP_KEY_AGREEMENT_K255_KYB512
|
||||
chat_messages_aggregation_delay=1000
|
||||
chat_messages_aggregation=1
|
||||
update_presence_model_timestamp_before_publish_expires_refresh=1
|
||||
rls_uri=sips:rls@sip.linphone.org
|
||||
|
||||
[sound]
|
||||
#remove this property for any application that is not Linphone public version itself
|
||||
ec_calibrator_cool_tones=1
|
||||
|
||||
[video]
|
||||
displaytype=MSAndroidTextureDisplay
|
||||
auto_resize_preview_to_keep_ratio=1
|
||||
max_conference_size=vga
|
||||
|
||||
[misc]
|
||||
enable_basic_to_client_group_chat_room_migration=0
|
||||
enable_simple_group_chat_message_state=0
|
||||
aggregate_imdn=1
|
||||
notify_each_friend_individually_when_presence_received=0
|
||||
store_friends=0
|
||||
|
||||
[app]
|
||||
activation_code_length=4
|
||||
prefer_basic_chat_room=1
|
||||
record_aware=1
|
||||
|
||||
[account_creator]
|
||||
backend=1
|
||||
# 1 means FlexiAPI, 0 is XMLRPC
|
||||
url=https://subscribe.linphone.org/api/
|
||||
# replace above URL by https://staging-subscribe.linphone.org/api/ for testing
|
||||
|
||||
[lime]
|
||||
lime_update_threshold=86400
|
||||
|
||||
[alerts]
|
||||
alerts_enabled=1
|
||||
|
||||
[assistant]
|
||||
algorithm=SHA-256
|
||||
password_min_length=6
|
||||
username_regex=^[a-z0-9+_.\-]*$
|
||||
|
||||
## End of factory rc
|
||||
|
|
@ -113,28 +113,9 @@ struct ContactInnerFragment: View {
|
|||
&& magicSearch.lastSearch[contactViewModel.indexDisplayedFriend!].friend != nil
|
||||
&& magicSearch.lastSearch[contactViewModel.indexDisplayedFriend!].friend!.photo != nil
|
||||
&& !magicSearch.lastSearch[contactViewModel.indexDisplayedFriend!].friend!.photo!.isEmpty {
|
||||
AsyncImage(
|
||||
url: ContactsManager.shared.getImagePath(
|
||||
friendPhotoPath: magicSearch.lastSearch[contactViewModel.indexDisplayedFriend!].friend!.photo!)) { image in
|
||||
switch image {
|
||||
case .empty:
|
||||
ProgressView()
|
||||
.frame(width: 100, height: 100)
|
||||
case .success(let image):
|
||||
image
|
||||
.resizable()
|
||||
.aspectRatio(contentMode: .fill)
|
||||
.frame(width: 100, height: 100)
|
||||
.clipShape(Circle())
|
||||
case .failure:
|
||||
Image("profil-picture-default")
|
||||
.resizable()
|
||||
.frame(width: 100, height: 100)
|
||||
.clipShape(Circle())
|
||||
@unknown default:
|
||||
EmptyView()
|
||||
}
|
||||
}
|
||||
|
||||
Avatar(friend: magicSearch.lastSearch[contactViewModel.indexDisplayedFriend!].friend!, avatarSize: 100)
|
||||
|
||||
} else if contactViewModel.indexDisplayedFriend != nil && magicSearch.lastSearch[contactViewModel.indexDisplayedFriend!].friend != nil {
|
||||
Image("profil-picture-default")
|
||||
.resizable()
|
||||
|
|
|
|||
|
|
@ -64,26 +64,9 @@ struct ContactsListFragment: View {
|
|||
}
|
||||
|
||||
if magicSearch.lastSearch[index].friend!.photo != nil && !magicSearch.lastSearch[index].friend!.photo!.isEmpty {
|
||||
AsyncImage(url: ContactsManager.shared.getImagePath(friendPhotoPath: magicSearch.lastSearch[index].friend!.photo!)) { image in
|
||||
switch image {
|
||||
case .empty:
|
||||
ProgressView()
|
||||
.frame(width: 45, height: 45)
|
||||
case .success(let image):
|
||||
image
|
||||
.resizable()
|
||||
.aspectRatio(contentMode: .fill)
|
||||
.frame(width: 45, height: 45)
|
||||
.clipShape(Circle())
|
||||
case .failure:
|
||||
Image("profil-picture-default")
|
||||
.resizable()
|
||||
.frame(width: 45, height: 45)
|
||||
.clipShape(Circle())
|
||||
@unknown default:
|
||||
EmptyView()
|
||||
}
|
||||
}
|
||||
|
||||
Avatar(friend: magicSearch.lastSearch[index].friend!, avatarSize: 45)
|
||||
|
||||
} else {
|
||||
Image("profil-picture-default")
|
||||
.resizable()
|
||||
|
|
|
|||
|
|
@ -129,26 +129,9 @@ struct EditContactFragment: View {
|
|||
if editContactViewModel.selectedEditFriend != nil
|
||||
&& editContactViewModel.selectedEditFriend!.photo != nil
|
||||
&& !editContactViewModel.selectedEditFriend!.photo!.isEmpty && selectedImage == nil && !removedImage {
|
||||
AsyncImage(url: ContactsManager.shared.getImagePath(friendPhotoPath: editContactViewModel.selectedEditFriend!.photo!)) { image in
|
||||
switch image {
|
||||
case .empty:
|
||||
ProgressView()
|
||||
.frame(width: 100, height: 100)
|
||||
case .success(let image):
|
||||
image
|
||||
.resizable()
|
||||
.aspectRatio(contentMode: .fill)
|
||||
.frame(width: 100, height: 100)
|
||||
.clipShape(Circle())
|
||||
case .failure:
|
||||
Image("profil-picture-default")
|
||||
.resizable()
|
||||
.frame(width: 100, height: 100)
|
||||
.clipShape(Circle())
|
||||
@unknown default:
|
||||
EmptyView()
|
||||
}
|
||||
}
|
||||
|
||||
Avatar(friend: editContactViewModel.selectedEditFriend!, avatarSize: 100)
|
||||
|
||||
} else if selectedImage == nil {
|
||||
Image("profil-picture-default")
|
||||
.resizable()
|
||||
|
|
|
|||
|
|
@ -39,27 +39,9 @@ struct FavoriteContactsListFragment: View {
|
|||
VStack {
|
||||
if magicSearch.lastSearch[index].friend!.photo != nil
|
||||
&& !magicSearch.lastSearch[index].friend!.photo!.isEmpty {
|
||||
AsyncImage(url: ContactsManager.shared.getImagePath(friendPhotoPath: magicSearch.lastSearch[index].friend!.photo!)
|
||||
) { image in
|
||||
switch image {
|
||||
case .empty:
|
||||
ProgressView()
|
||||
.frame(width: 45, height: 45)
|
||||
case .success(let image):
|
||||
image
|
||||
.resizable()
|
||||
.aspectRatio(contentMode: .fill)
|
||||
.frame(width: 45, height: 45)
|
||||
.clipShape(Circle())
|
||||
case .failure:
|
||||
Image("profil-picture-default")
|
||||
.resizable()
|
||||
.frame(width: 45, height: 45)
|
||||
.clipShape(Circle())
|
||||
@unknown default:
|
||||
EmptyView()
|
||||
}
|
||||
}
|
||||
|
||||
Avatar(friend: magicSearch.lastSearch[index].friend!, avatarSize: 45)
|
||||
|
||||
} else {
|
||||
Image("profil-picture-default")
|
||||
.resizable()
|
||||
|
|
|
|||
|
|
@ -136,6 +136,7 @@ struct ContentView: View {
|
|||
Menu {
|
||||
Button {
|
||||
isMenuOpen = false
|
||||
contactViewModel.indexDisplayedFriend = nil
|
||||
magicSearch.allContact = true
|
||||
magicSearch.searchForContacts(
|
||||
sourceFlags: MagicSearch.Source.Friends.rawValue | MagicSearch.Source.LdapServers.rawValue)
|
||||
|
|
@ -153,6 +154,7 @@ struct ContentView: View {
|
|||
|
||||
Button {
|
||||
isMenuOpen = false
|
||||
contactViewModel.indexDisplayedFriend = nil
|
||||
magicSearch.allContact = false
|
||||
magicSearch.searchForContacts(
|
||||
sourceFlags: MagicSearch.Source.Friends.rawValue | MagicSearch.Source.LdapServers.rawValue)
|
||||
|
|
|
|||
118
Linphone/Utils/Avatar.swift
Normal file
118
Linphone/Utils/Avatar.swift
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2023 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
|
||||
import linphonesw
|
||||
|
||||
struct Avatar: View {
|
||||
var friend: Friend
|
||||
let avatarSize: CGFloat
|
||||
|
||||
@State private var friendDelegate: FriendDelegate?
|
||||
@State private var presenceImage = ""
|
||||
|
||||
var body: some View {
|
||||
AsyncImage(url: ContactsManager.shared.getImagePath(friendPhotoPath: friend.photo!)) { image in
|
||||
switch image {
|
||||
case .empty:
|
||||
ProgressView()
|
||||
.frame(width: avatarSize, height: avatarSize)
|
||||
case .success(let image):
|
||||
ZStack {
|
||||
image
|
||||
.resizable()
|
||||
.aspectRatio(contentMode: .fill)
|
||||
.frame(width: avatarSize, height: avatarSize)
|
||||
.clipShape(Circle())
|
||||
HStack {
|
||||
Spacer()
|
||||
VStack {
|
||||
Spacer()
|
||||
if !friend.addresses.isEmpty {
|
||||
if presenceImage.isEmpty && (friend.consolidatedPresence == ConsolidatedPresence.Online || friend.consolidatedPresence == ConsolidatedPresence.Busy) {
|
||||
Image(friend.consolidatedPresence == ConsolidatedPresence.Online ? "presence-online" : "presence-busy")
|
||||
.resizable()
|
||||
.frame(width: avatarSize/4, height: avatarSize/4)
|
||||
.padding(.trailing, avatarSize == 45 ? 1 : 3)
|
||||
.padding(.bottom, avatarSize == 45 ? 1 : 3)
|
||||
} else if !presenceImage.isEmpty && (friend.consolidatedPresence != ConsolidatedPresence.DoNotDisturb || friend.consolidatedPresence != ConsolidatedPresence.Offline) {
|
||||
Image(presenceImage)
|
||||
.resizable()
|
||||
.frame(width: avatarSize/4, height: avatarSize/4)
|
||||
.padding(.trailing, avatarSize == 45 ? 1 : 3)
|
||||
.padding(.bottom, avatarSize == 45 ? 1 : 3)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.frame(width: avatarSize, height: avatarSize)
|
||||
}
|
||||
case .failure:
|
||||
Image("profil-picture-default")
|
||||
.resizable()
|
||||
.frame(width: avatarSize, height: avatarSize)
|
||||
.clipShape(Circle())
|
||||
@unknown default:
|
||||
EmptyView()
|
||||
}
|
||||
}
|
||||
.onAppear {
|
||||
addDelegate()
|
||||
}
|
||||
.onDisappear {
|
||||
removeAllDelegate()
|
||||
}
|
||||
}
|
||||
|
||||
func addDelegate() {
|
||||
if friend.address != nil {
|
||||
print("Presence received for first \(friend.name!) \(friend.consolidatedPresence)")
|
||||
//self.presenceImage = friend.consolidatedPresence == ConsolidatedPresence.Online ? "presence-online" : "presence-busy"
|
||||
}
|
||||
|
||||
let newFriendDelegate = FriendDelegateStub(
|
||||
onPresenceReceived: { (linphoneFriend: Friend) -> Void in
|
||||
print("Presence received for second \(linphoneFriend.name) \(linphoneFriend.consolidatedPresence)")
|
||||
|
||||
/*
|
||||
if linphoneFriend.address != nil && friend.address != nil
|
||||
&& linphoneFriend.address!.asStringUriOnly() == friend.address!.asStringUriOnly() {
|
||||
let presenceModel = linphoneFriend.getPresenceModelForUriOrTel(uriOrTel: (linphoneFriend.address!.asStringUriOnly()))
|
||||
if presenceModel != nil {
|
||||
presenceImage = presenceModel!.consolidatedPresence == ConsolidatedPresence.Online ? "presence-online" : "presence-busy"
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
)
|
||||
|
||||
friendDelegate = newFriendDelegate
|
||||
if friendDelegate != nil {
|
||||
friend.addDelegate(delegate: friendDelegate!)
|
||||
}
|
||||
}
|
||||
|
||||
func removeAllDelegate(){
|
||||
if friendDelegate != nil {
|
||||
presenceImage = ""
|
||||
friend.removeDelegate(delegate: friendDelegate!)
|
||||
friendDelegate = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue