diff --git a/WireCalling/Package.swift b/WireCalling/Package.swift index 866b45aacb6..ad5b1c47835 100644 --- a/WireCalling/Package.swift +++ b/WireCalling/Package.swift @@ -11,8 +11,9 @@ let package = Package( .library(name: "WireCallingUI", targets: ["WireCallingUI"]) ], dependencies: [ - .package(path: "../WireFoundation"), - .package(path: "../WireUI") + .package(name: "WireFoundation", path: "../WireFoundation"), + .package(path: "../WirePlugins"), + .package(name: "WireUI", path: "../WireUI") ], targets: [ .target( @@ -20,8 +21,10 @@ let package = Package( dependencies: [ .product(name: "WireDesign", package: "WireUI"), .product(name: "WireReusableUIComponents", package: "WireUI"), + .product(name: "WireAccountImageUI", package: "WireUI"), "WireFoundation" ], + plugins: [.plugin(name: "SwiftGenPlugin", package: "WirePlugins")] ), .testTarget( name: "WireCallingTests", diff --git a/WireCalling/Sources/WireCallingUI/.swiftgen.yml b/WireCalling/Sources/WireCallingUI/.swiftgen.yml new file mode 100644 index 00000000000..e5f2e8becda --- /dev/null +++ b/WireCalling/Sources/WireCallingUI/.swiftgen.yml @@ -0,0 +1,15 @@ +# Every input/output paths in the rest of the config will then be expressed relative to these. + +input_dir: ./ +output_dir: ${GENERATED}/ + +# Generate constants for your localized strings. + +strings: + inputs: + - Resources/Localization/en.lproj/Localizable.strings + - Resources/Localization/en.lproj/Accessibility.strings + filter: + outputs: + - templateName: structured-swift5 + output: Strings+Generated.swift diff --git a/WireCalling/Sources/WireCallingUI/Resources/Images.xcassets/Contents.json b/WireCalling/Sources/WireCallingUI/Resources/Images.xcassets/Contents.json new file mode 100644 index 00000000000..73c00596a7f --- /dev/null +++ b/WireCalling/Sources/WireCallingUI/Resources/Images.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/WireCalling/Sources/WireCallingUI/Resources/Images.xcassets/VideoCall.imageset/Contents.json b/WireCalling/Sources/WireCallingUI/Resources/Images.xcassets/VideoCall.imageset/Contents.json new file mode 100644 index 00000000000..af3b035e2fe --- /dev/null +++ b/WireCalling/Sources/WireCallingUI/Resources/Images.xcassets/VideoCall.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "VideoCallFilled.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "template" + } +} diff --git a/WireCalling/Sources/WireCallingUI/Resources/Images.xcassets/VideoCall.imageset/VideoCallFilled.svg b/WireCalling/Sources/WireCallingUI/Resources/Images.xcassets/VideoCall.imageset/VideoCallFilled.svg new file mode 100644 index 00000000000..ce8f6a70196 --- /dev/null +++ b/WireCalling/Sources/WireCallingUI/Resources/Images.xcassets/VideoCall.imageset/VideoCallFilled.svg @@ -0,0 +1,4 @@ + + + + diff --git a/WireCalling/Sources/WireCallingUI/Resources/Images.xcassets/meetingsEmptyArrow.imageset/Contents.json b/WireCalling/Sources/WireCallingUI/Resources/Images.xcassets/meetingsEmptyArrow.imageset/Contents.json new file mode 100644 index 00000000000..9e5732f0d13 --- /dev/null +++ b/WireCalling/Sources/WireCallingUI/Resources/Images.xcassets/meetingsEmptyArrow.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "arrow1.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "template" + } +} diff --git a/WireCalling/Sources/WireCallingUI/Resources/Images.xcassets/meetingsEmptyArrow.imageset/arrow1.svg b/WireCalling/Sources/WireCallingUI/Resources/Images.xcassets/meetingsEmptyArrow.imageset/arrow1.svg new file mode 100644 index 00000000000..c28f79ebe5f --- /dev/null +++ b/WireCalling/Sources/WireCallingUI/Resources/Images.xcassets/meetingsEmptyArrow.imageset/arrow1.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/WireCalling/Sources/WireCallingUI/File.swift b/WireCalling/Sources/WireCallingUI/Resources/Localization/ar.lproj/Accessibility.strings similarity index 97% rename from WireCalling/Sources/WireCallingUI/File.swift rename to WireCalling/Sources/WireCallingUI/Resources/Localization/ar.lproj/Accessibility.strings index 45cad4d0330..89c90917712 100644 --- a/WireCalling/Sources/WireCallingUI/File.swift +++ b/WireCalling/Sources/WireCallingUI/Resources/Localization/ar.lproj/Accessibility.strings @@ -15,5 +15,3 @@ // 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 diff --git a/WireCalling/Sources/WireCallingUI/Resources/Localization/ar.lproj/Localizable.strings b/WireCalling/Sources/WireCallingUI/Resources/Localization/ar.lproj/Localizable.strings new file mode 100644 index 00000000000..89c90917712 --- /dev/null +++ b/WireCalling/Sources/WireCallingUI/Resources/Localization/ar.lproj/Localizable.strings @@ -0,0 +1,17 @@ +// +// Wire +// Copyright (C) 2025 Wire Swiss GmbH +// +// 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/. +// diff --git a/WireCalling/Sources/WireCallingUI/Resources/Localization/da.lproj/Accessibility.strings b/WireCalling/Sources/WireCallingUI/Resources/Localization/da.lproj/Accessibility.strings new file mode 100644 index 00000000000..89c90917712 --- /dev/null +++ b/WireCalling/Sources/WireCallingUI/Resources/Localization/da.lproj/Accessibility.strings @@ -0,0 +1,17 @@ +// +// Wire +// Copyright (C) 2025 Wire Swiss GmbH +// +// 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/. +// diff --git a/WireCalling/Sources/WireCallingUI/Resources/Localization/da.lproj/Localizable.strings b/WireCalling/Sources/WireCallingUI/Resources/Localization/da.lproj/Localizable.strings new file mode 100644 index 00000000000..89c90917712 --- /dev/null +++ b/WireCalling/Sources/WireCallingUI/Resources/Localization/da.lproj/Localizable.strings @@ -0,0 +1,17 @@ +// +// Wire +// Copyright (C) 2025 Wire Swiss GmbH +// +// 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/. +// diff --git a/WireCalling/Sources/WireCallingUI/Resources/Localization/de.lproj/Accessibility.strings b/WireCalling/Sources/WireCallingUI/Resources/Localization/de.lproj/Accessibility.strings new file mode 100644 index 00000000000..89c90917712 --- /dev/null +++ b/WireCalling/Sources/WireCallingUI/Resources/Localization/de.lproj/Accessibility.strings @@ -0,0 +1,17 @@ +// +// Wire +// Copyright (C) 2025 Wire Swiss GmbH +// +// 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/. +// diff --git a/WireCalling/Sources/WireCallingUI/Resources/Localization/de.lproj/Localizable.strings b/WireCalling/Sources/WireCallingUI/Resources/Localization/de.lproj/Localizable.strings new file mode 100644 index 00000000000..89c90917712 --- /dev/null +++ b/WireCalling/Sources/WireCallingUI/Resources/Localization/de.lproj/Localizable.strings @@ -0,0 +1,17 @@ +// +// Wire +// Copyright (C) 2025 Wire Swiss GmbH +// +// 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/. +// diff --git a/WireCalling/Sources/WireCallingUI/Resources/Localization/en.lproj/Accessibility.strings b/WireCalling/Sources/WireCallingUI/Resources/Localization/en.lproj/Accessibility.strings new file mode 100644 index 00000000000..89c90917712 --- /dev/null +++ b/WireCalling/Sources/WireCallingUI/Resources/Localization/en.lproj/Accessibility.strings @@ -0,0 +1,17 @@ +// +// Wire +// Copyright (C) 2025 Wire Swiss GmbH +// +// 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/. +// diff --git a/WireCalling/Sources/WireCallingUI/Resources/Localization/en.lproj/Localizable.strings b/WireCalling/Sources/WireCallingUI/Resources/Localization/en.lproj/Localizable.strings new file mode 100644 index 00000000000..a998d27343e --- /dev/null +++ b/WireCalling/Sources/WireCallingUI/Resources/Localization/en.lproj/Localizable.strings @@ -0,0 +1,27 @@ +// +// Wire +// Copyright (C) 2025 Wire Swiss GmbH +// +// 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/. +// + +// MARK: - Meetings List + +"wireMeetings.list.title" = "Meetings"; +"wireMeetings.list.tabs.past" = "Past"; +"wireMeetings.list.tabs.upcoming" = "Upcoming"; +"wireMeetings.list.actions.meetNow" = "Meet Now"; +"wireMeetings.list.actions.scheduleMeeting" = "Schedule a Meeting"; +"wireMeetings.list.emptyState.title" = "No meetings yet"; +"wireMeetings.list.emptyState.subtitle" = "Start a meeting with team members, guests, or external parties."; diff --git a/WireCalling/Sources/WireCallingUI/Resources/Localization/es.lproj/Accessibility.strings b/WireCalling/Sources/WireCallingUI/Resources/Localization/es.lproj/Accessibility.strings new file mode 100644 index 00000000000..89c90917712 --- /dev/null +++ b/WireCalling/Sources/WireCallingUI/Resources/Localization/es.lproj/Accessibility.strings @@ -0,0 +1,17 @@ +// +// Wire +// Copyright (C) 2025 Wire Swiss GmbH +// +// 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/. +// diff --git a/WireCalling/Sources/WireCallingUI/Resources/Localization/es.lproj/Localizable.strings b/WireCalling/Sources/WireCallingUI/Resources/Localization/es.lproj/Localizable.strings new file mode 100644 index 00000000000..89c90917712 --- /dev/null +++ b/WireCalling/Sources/WireCallingUI/Resources/Localization/es.lproj/Localizable.strings @@ -0,0 +1,17 @@ +// +// Wire +// Copyright (C) 2025 Wire Swiss GmbH +// +// 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/. +// diff --git a/WireCalling/Sources/WireCallingUI/Resources/Localization/et.lproj/Accessibility.strings b/WireCalling/Sources/WireCallingUI/Resources/Localization/et.lproj/Accessibility.strings new file mode 100644 index 00000000000..89c90917712 --- /dev/null +++ b/WireCalling/Sources/WireCallingUI/Resources/Localization/et.lproj/Accessibility.strings @@ -0,0 +1,17 @@ +// +// Wire +// Copyright (C) 2025 Wire Swiss GmbH +// +// 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/. +// diff --git a/WireCalling/Sources/WireCallingUI/Resources/Localization/et.lproj/Localizable.strings b/WireCalling/Sources/WireCallingUI/Resources/Localization/et.lproj/Localizable.strings new file mode 100644 index 00000000000..89c90917712 --- /dev/null +++ b/WireCalling/Sources/WireCallingUI/Resources/Localization/et.lproj/Localizable.strings @@ -0,0 +1,17 @@ +// +// Wire +// Copyright (C) 2025 Wire Swiss GmbH +// +// 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/. +// diff --git a/WireCalling/Sources/WireCallingUI/Resources/Localization/fi.lproj/Accessibility.strings b/WireCalling/Sources/WireCallingUI/Resources/Localization/fi.lproj/Accessibility.strings new file mode 100644 index 00000000000..89c90917712 --- /dev/null +++ b/WireCalling/Sources/WireCallingUI/Resources/Localization/fi.lproj/Accessibility.strings @@ -0,0 +1,17 @@ +// +// Wire +// Copyright (C) 2025 Wire Swiss GmbH +// +// 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/. +// diff --git a/WireCalling/Sources/WireCallingUI/Resources/Localization/fi.lproj/Localizable.strings b/WireCalling/Sources/WireCallingUI/Resources/Localization/fi.lproj/Localizable.strings new file mode 100644 index 00000000000..89c90917712 --- /dev/null +++ b/WireCalling/Sources/WireCallingUI/Resources/Localization/fi.lproj/Localizable.strings @@ -0,0 +1,17 @@ +// +// Wire +// Copyright (C) 2025 Wire Swiss GmbH +// +// 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/. +// diff --git a/WireCalling/Sources/WireCallingUI/Resources/Localization/fr.lproj/Accessibility.strings b/WireCalling/Sources/WireCallingUI/Resources/Localization/fr.lproj/Accessibility.strings new file mode 100644 index 00000000000..89c90917712 --- /dev/null +++ b/WireCalling/Sources/WireCallingUI/Resources/Localization/fr.lproj/Accessibility.strings @@ -0,0 +1,17 @@ +// +// Wire +// Copyright (C) 2025 Wire Swiss GmbH +// +// 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/. +// diff --git a/WireCalling/Sources/WireCallingUI/Resources/Localization/fr.lproj/Localizable.strings b/WireCalling/Sources/WireCallingUI/Resources/Localization/fr.lproj/Localizable.strings new file mode 100644 index 00000000000..89c90917712 --- /dev/null +++ b/WireCalling/Sources/WireCallingUI/Resources/Localization/fr.lproj/Localizable.strings @@ -0,0 +1,17 @@ +// +// Wire +// Copyright (C) 2025 Wire Swiss GmbH +// +// 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/. +// diff --git a/WireCalling/Sources/WireCallingUI/Resources/Localization/it.lproj/Accessibility.strings b/WireCalling/Sources/WireCallingUI/Resources/Localization/it.lproj/Accessibility.strings new file mode 100644 index 00000000000..89c90917712 --- /dev/null +++ b/WireCalling/Sources/WireCallingUI/Resources/Localization/it.lproj/Accessibility.strings @@ -0,0 +1,17 @@ +// +// Wire +// Copyright (C) 2025 Wire Swiss GmbH +// +// 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/. +// diff --git a/WireCalling/Sources/WireCallingUI/Resources/Localization/it.lproj/Localizable.strings b/WireCalling/Sources/WireCallingUI/Resources/Localization/it.lproj/Localizable.strings new file mode 100644 index 00000000000..89c90917712 --- /dev/null +++ b/WireCalling/Sources/WireCallingUI/Resources/Localization/it.lproj/Localizable.strings @@ -0,0 +1,17 @@ +// +// Wire +// Copyright (C) 2025 Wire Swiss GmbH +// +// 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/. +// diff --git a/WireCalling/Sources/WireCallingUI/Resources/Localization/ja.lproj/Accessibility.strings b/WireCalling/Sources/WireCallingUI/Resources/Localization/ja.lproj/Accessibility.strings new file mode 100644 index 00000000000..89c90917712 --- /dev/null +++ b/WireCalling/Sources/WireCallingUI/Resources/Localization/ja.lproj/Accessibility.strings @@ -0,0 +1,17 @@ +// +// Wire +// Copyright (C) 2025 Wire Swiss GmbH +// +// 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/. +// diff --git a/WireCalling/Sources/WireCallingUI/Resources/Localization/ja.lproj/Localizable.strings b/WireCalling/Sources/WireCallingUI/Resources/Localization/ja.lproj/Localizable.strings new file mode 100644 index 00000000000..89c90917712 --- /dev/null +++ b/WireCalling/Sources/WireCallingUI/Resources/Localization/ja.lproj/Localizable.strings @@ -0,0 +1,17 @@ +// +// Wire +// Copyright (C) 2025 Wire Swiss GmbH +// +// 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/. +// diff --git a/WireCalling/Sources/WireCallingUI/Resources/Localization/lt.lproj/Accessibility.strings b/WireCalling/Sources/WireCallingUI/Resources/Localization/lt.lproj/Accessibility.strings new file mode 100644 index 00000000000..89c90917712 --- /dev/null +++ b/WireCalling/Sources/WireCallingUI/Resources/Localization/lt.lproj/Accessibility.strings @@ -0,0 +1,17 @@ +// +// Wire +// Copyright (C) 2025 Wire Swiss GmbH +// +// 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/. +// diff --git a/WireCalling/Sources/WireCallingUI/Resources/Localization/lt.lproj/Localizable.strings b/WireCalling/Sources/WireCallingUI/Resources/Localization/lt.lproj/Localizable.strings new file mode 100644 index 00000000000..89c90917712 --- /dev/null +++ b/WireCalling/Sources/WireCallingUI/Resources/Localization/lt.lproj/Localizable.strings @@ -0,0 +1,17 @@ +// +// Wire +// Copyright (C) 2025 Wire Swiss GmbH +// +// 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/. +// diff --git a/WireCalling/Sources/WireCallingUI/Resources/Localization/nl.lproj/Accessibility.strings b/WireCalling/Sources/WireCallingUI/Resources/Localization/nl.lproj/Accessibility.strings new file mode 100644 index 00000000000..89c90917712 --- /dev/null +++ b/WireCalling/Sources/WireCallingUI/Resources/Localization/nl.lproj/Accessibility.strings @@ -0,0 +1,17 @@ +// +// Wire +// Copyright (C) 2025 Wire Swiss GmbH +// +// 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/. +// diff --git a/WireCalling/Sources/WireCallingUI/Resources/Localization/nl.lproj/Localizable.strings b/WireCalling/Sources/WireCallingUI/Resources/Localization/nl.lproj/Localizable.strings new file mode 100644 index 00000000000..89c90917712 --- /dev/null +++ b/WireCalling/Sources/WireCallingUI/Resources/Localization/nl.lproj/Localizable.strings @@ -0,0 +1,17 @@ +// +// Wire +// Copyright (C) 2025 Wire Swiss GmbH +// +// 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/. +// diff --git a/WireCalling/Sources/WireCallingUI/Resources/Localization/pl.lproj/Accessibility.strings b/WireCalling/Sources/WireCallingUI/Resources/Localization/pl.lproj/Accessibility.strings new file mode 100644 index 00000000000..89c90917712 --- /dev/null +++ b/WireCalling/Sources/WireCallingUI/Resources/Localization/pl.lproj/Accessibility.strings @@ -0,0 +1,17 @@ +// +// Wire +// Copyright (C) 2025 Wire Swiss GmbH +// +// 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/. +// diff --git a/WireCalling/Sources/WireCallingUI/Resources/Localization/pl.lproj/Localizable.strings b/WireCalling/Sources/WireCallingUI/Resources/Localization/pl.lproj/Localizable.strings new file mode 100644 index 00000000000..89c90917712 --- /dev/null +++ b/WireCalling/Sources/WireCallingUI/Resources/Localization/pl.lproj/Localizable.strings @@ -0,0 +1,17 @@ +// +// Wire +// Copyright (C) 2025 Wire Swiss GmbH +// +// 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/. +// diff --git a/WireCalling/Sources/WireCallingUI/Resources/Localization/pt-BR.lproj/Accessibility.strings b/WireCalling/Sources/WireCallingUI/Resources/Localization/pt-BR.lproj/Accessibility.strings new file mode 100644 index 00000000000..89c90917712 --- /dev/null +++ b/WireCalling/Sources/WireCallingUI/Resources/Localization/pt-BR.lproj/Accessibility.strings @@ -0,0 +1,17 @@ +// +// Wire +// Copyright (C) 2025 Wire Swiss GmbH +// +// 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/. +// diff --git a/WireCalling/Sources/WireCallingUI/Resources/Localization/pt-BR.lproj/Localizable.strings b/WireCalling/Sources/WireCallingUI/Resources/Localization/pt-BR.lproj/Localizable.strings new file mode 100644 index 00000000000..89c90917712 --- /dev/null +++ b/WireCalling/Sources/WireCallingUI/Resources/Localization/pt-BR.lproj/Localizable.strings @@ -0,0 +1,17 @@ +// +// Wire +// Copyright (C) 2025 Wire Swiss GmbH +// +// 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/. +// diff --git a/WireCalling/Sources/WireCallingUI/Resources/Localization/ru.lproj/Accessibility.strings b/WireCalling/Sources/WireCallingUI/Resources/Localization/ru.lproj/Accessibility.strings new file mode 100644 index 00000000000..89c90917712 --- /dev/null +++ b/WireCalling/Sources/WireCallingUI/Resources/Localization/ru.lproj/Accessibility.strings @@ -0,0 +1,17 @@ +// +// Wire +// Copyright (C) 2025 Wire Swiss GmbH +// +// 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/. +// diff --git a/WireCalling/Sources/WireCallingUI/Resources/Localization/ru.lproj/Localizable.strings b/WireCalling/Sources/WireCallingUI/Resources/Localization/ru.lproj/Localizable.strings new file mode 100644 index 00000000000..89c90917712 --- /dev/null +++ b/WireCalling/Sources/WireCallingUI/Resources/Localization/ru.lproj/Localizable.strings @@ -0,0 +1,17 @@ +// +// Wire +// Copyright (C) 2025 Wire Swiss GmbH +// +// 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/. +// diff --git a/WireCalling/Sources/WireCallingUI/Resources/Localization/sl.lproj/Accessibility.strings b/WireCalling/Sources/WireCallingUI/Resources/Localization/sl.lproj/Accessibility.strings new file mode 100644 index 00000000000..89c90917712 --- /dev/null +++ b/WireCalling/Sources/WireCallingUI/Resources/Localization/sl.lproj/Accessibility.strings @@ -0,0 +1,17 @@ +// +// Wire +// Copyright (C) 2025 Wire Swiss GmbH +// +// 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/. +// diff --git a/WireCalling/Sources/WireCallingUI/Resources/Localization/sl.lproj/Localizable.strings b/WireCalling/Sources/WireCallingUI/Resources/Localization/sl.lproj/Localizable.strings new file mode 100644 index 00000000000..89c90917712 --- /dev/null +++ b/WireCalling/Sources/WireCallingUI/Resources/Localization/sl.lproj/Localizable.strings @@ -0,0 +1,17 @@ +// +// Wire +// Copyright (C) 2025 Wire Swiss GmbH +// +// 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/. +// diff --git a/WireCalling/Sources/WireCallingUI/Resources/Localization/tr.lproj/Accessibility.strings b/WireCalling/Sources/WireCallingUI/Resources/Localization/tr.lproj/Accessibility.strings new file mode 100644 index 00000000000..89c90917712 --- /dev/null +++ b/WireCalling/Sources/WireCallingUI/Resources/Localization/tr.lproj/Accessibility.strings @@ -0,0 +1,17 @@ +// +// Wire +// Copyright (C) 2025 Wire Swiss GmbH +// +// 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/. +// diff --git a/WireCalling/Sources/WireCallingUI/Resources/Localization/tr.lproj/Localizable.strings b/WireCalling/Sources/WireCallingUI/Resources/Localization/tr.lproj/Localizable.strings new file mode 100644 index 00000000000..89c90917712 --- /dev/null +++ b/WireCalling/Sources/WireCallingUI/Resources/Localization/tr.lproj/Localizable.strings @@ -0,0 +1,17 @@ +// +// Wire +// Copyright (C) 2025 Wire Swiss GmbH +// +// 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/. +// diff --git a/WireCalling/Sources/WireCallingUI/Resources/Localization/uk.lproj/Accessibility.strings b/WireCalling/Sources/WireCallingUI/Resources/Localization/uk.lproj/Accessibility.strings new file mode 100644 index 00000000000..89c90917712 --- /dev/null +++ b/WireCalling/Sources/WireCallingUI/Resources/Localization/uk.lproj/Accessibility.strings @@ -0,0 +1,17 @@ +// +// Wire +// Copyright (C) 2025 Wire Swiss GmbH +// +// 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/. +// diff --git a/WireCalling/Sources/WireCallingUI/Resources/Localization/uk.lproj/Localizable.strings b/WireCalling/Sources/WireCallingUI/Resources/Localization/uk.lproj/Localizable.strings new file mode 100644 index 00000000000..89c90917712 --- /dev/null +++ b/WireCalling/Sources/WireCallingUI/Resources/Localization/uk.lproj/Localizable.strings @@ -0,0 +1,17 @@ +// +// Wire +// Copyright (C) 2025 Wire Swiss GmbH +// +// 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/. +// diff --git a/WireCalling/Sources/WireCallingUI/Resources/Localization/zh-Hans.lproj/Accessibility.strings b/WireCalling/Sources/WireCallingUI/Resources/Localization/zh-Hans.lproj/Accessibility.strings new file mode 100644 index 00000000000..89c90917712 --- /dev/null +++ b/WireCalling/Sources/WireCallingUI/Resources/Localization/zh-Hans.lproj/Accessibility.strings @@ -0,0 +1,17 @@ +// +// Wire +// Copyright (C) 2025 Wire Swiss GmbH +// +// 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/. +// diff --git a/WireCalling/Sources/WireCallingUI/Resources/Localization/zh-Hans.lproj/Localizable.strings b/WireCalling/Sources/WireCallingUI/Resources/Localization/zh-Hans.lproj/Localizable.strings new file mode 100644 index 00000000000..89c90917712 --- /dev/null +++ b/WireCalling/Sources/WireCallingUI/Resources/Localization/zh-Hans.lproj/Localizable.strings @@ -0,0 +1,17 @@ +// +// Wire +// Copyright (C) 2025 Wire Swiss GmbH +// +// 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/. +// diff --git a/WireCalling/Sources/WireCallingUI/Resources/Localization/zh-Hant.lproj/Accessibility.strings b/WireCalling/Sources/WireCallingUI/Resources/Localization/zh-Hant.lproj/Accessibility.strings new file mode 100644 index 00000000000..89c90917712 --- /dev/null +++ b/WireCalling/Sources/WireCallingUI/Resources/Localization/zh-Hant.lproj/Accessibility.strings @@ -0,0 +1,17 @@ +// +// Wire +// Copyright (C) 2025 Wire Swiss GmbH +// +// 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/. +// diff --git a/WireCalling/Sources/WireCallingUI/Resources/Localization/zh-Hant.lproj/Localizable.strings b/WireCalling/Sources/WireCallingUI/Resources/Localization/zh-Hant.lproj/Localizable.strings new file mode 100644 index 00000000000..89c90917712 --- /dev/null +++ b/WireCalling/Sources/WireCallingUI/Resources/Localization/zh-Hant.lproj/Localizable.strings @@ -0,0 +1,17 @@ +// +// Wire +// Copyright (C) 2025 Wire Swiss GmbH +// +// 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/. +// diff --git a/WireCalling/Sources/WireCallingUI/Resources/UImage+ImageResource.swift b/WireCalling/Sources/WireCallingUI/Resources/UImage+ImageResource.swift new file mode 100644 index 00000000000..87b5a169ccc --- /dev/null +++ b/WireCalling/Sources/WireCallingUI/Resources/UImage+ImageResource.swift @@ -0,0 +1,23 @@ +// +// Wire +// Copyright (C) 2025 Wire Swiss GmbH +// +// 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 UIKit + +extension UIImage { + static let videoCall = UIImage(resource: .videoCall) +} diff --git a/WireCalling/Sources/WireCallingUI/WireMeetings/AccountView/AccountUI.swift b/WireCalling/Sources/WireCallingUI/WireMeetings/AccountView/AccountUI.swift new file mode 100644 index 00000000000..66c952598ea --- /dev/null +++ b/WireCalling/Sources/WireCallingUI/WireMeetings/AccountView/AccountUI.swift @@ -0,0 +1,49 @@ +// +// Wire +// Copyright (C) 2025 Wire Swiss GmbH +// +// 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 WireAccountImageUI +import WireDesign + +struct AccountUI: View { + private let viewModel: AccountUIViewModel + + init(viewModel: AccountUIViewModel) { + self.viewModel = viewModel + } + + var body: some View { + let accountImageViewDesign = AccountImageViewDesign() + let availabilityIndicatorDesign = accountImageViewDesign.availabilityIndicator + HStack(spacing: 4) { + AccountImageViewRepresentable( + source: viewModel.avatarSource, + availability: viewModel.availability, + showNotificationsBadge: false + ) + .accountImageBorderWidth(accountImageViewDesign.borderWidth) + .accountImageViewBorderColor(accountImageViewDesign.borderColor) + .availabilityIndicatorAvailableColor(availabilityIndicatorDesign.availableColor) + .availabilityIndicatorAwayColor(availabilityIndicatorDesign.awayColor) + .availabilityIndicatorBusyColor(availabilityIndicatorDesign.busyColor) + .availabilityIndicatorBackgroundViewColor(availabilityIndicatorDesign.backgroundViewColor) + .frame(width: 28, height: 28) + } + .fixedSize() + } +} diff --git a/WireCalling/Sources/WireCallingUI/WireMeetings/AccountView/AccountUIViewModel.swift b/WireCalling/Sources/WireCallingUI/WireMeetings/AccountView/AccountUIViewModel.swift new file mode 100644 index 00000000000..49c13ac0640 --- /dev/null +++ b/WireCalling/Sources/WireCallingUI/WireMeetings/AccountView/AccountUIViewModel.swift @@ -0,0 +1,38 @@ +// +// Wire +// Copyright (C) 2025 Wire Swiss GmbH +// +// 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/. +// + +public import Foundation +public import WireAccountImageUI + +public struct AccountUIViewModel: Identifiable { + public let id = UUID() + + let avatarSource: AccountImageSource + let availability: Availability? + public let action: () -> Void + + public init( + avatarSource: AccountImageSource, + availability: Availability?, + action: @escaping () -> Void + ) { + self.avatarSource = avatarSource + self.availability = availability + self.action = action + } +} diff --git a/WireCalling/Sources/WireCallingUI/WireMeetings/AccountView/AccountUIWrapperView.swift b/WireCalling/Sources/WireCallingUI/WireMeetings/AccountView/AccountUIWrapperView.swift new file mode 100644 index 00000000000..4a06bb2d1a8 --- /dev/null +++ b/WireCalling/Sources/WireCallingUI/WireMeetings/AccountView/AccountUIWrapperView.swift @@ -0,0 +1,51 @@ +// +// Wire +// Copyright (C) 2025 Wire Swiss GmbH +// +// 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 Foundation +import WireAccountImageUI +import WireDesign + +final class AccountUIWrapperView: UIView { + private let hostingController: UIHostingController + + init(viewModel: AccountUIViewModel) { + hostingController = UIHostingController(rootView: AccountUI(viewModel: viewModel)) + super.init(frame: .zero) + + backgroundColor = .clear + hostingController.view.backgroundColor = .clear + + addSubview(hostingController.view) + hostingController.view.translatesAutoresizingMaskIntoConstraints = false + NSLayoutConstraint.activate([ + hostingController.view.leadingAnchor.constraint(equalTo: leadingAnchor), + hostingController.view.trailingAnchor.constraint(equalTo: trailingAnchor), + hostingController.view.topAnchor.constraint(equalTo: topAnchor), + hostingController.view.bottomAnchor.constraint(equalTo: bottomAnchor), + ]) + } + + func apply(account: AccountUIViewModel) { + hostingController.rootView = AccountUI(viewModel: account) + hostingController.view.setNeedsLayout() + } + + @available(*, unavailable) + required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } +} diff --git a/WireCalling/Sources/WireCallingUI/WireMeetings/MeetingsEmptyStateView.swift b/WireCalling/Sources/WireCallingUI/WireMeetings/MeetingsEmptyStateView.swift new file mode 100644 index 00000000000..fd62a331219 --- /dev/null +++ b/WireCalling/Sources/WireCallingUI/WireMeetings/MeetingsEmptyStateView.swift @@ -0,0 +1,68 @@ +// +// Wire +// Copyright (C) 2025 Wire Swiss GmbH +// +// 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 WireDesign + +package struct MeetingsEmptyStateView: View { + private typealias Strings = L10n.Localizable.WireMeetings.List.EmptyState + + var body: some View { + ZStack { + VStack(spacing: 28) { + Spacer(minLength: 0) + Text(Strings.title) + .font(.textStyle(.h2)) + .foregroundColor(ColorTheme.Backgrounds.onSurfaceVariant.color) + .multilineTextAlignment(.center) + .padding(.horizontal, 40) + .accessibilityIdentifier("meetingsEmptyStateTitle") + + Text(Strings.subtitle) + .font(.textStyle(.body1)) + .foregroundColor(ColorTheme.Backgrounds.onSurfaceVariant.color) + .multilineTextAlignment(.center) + .padding(.horizontal, 40) + .accessibilityIdentifier("meetingsEmptyStateSubtitle") + Spacer(minLength: 0) + } + } + .frame(maxWidth: .infinity, maxHeight: .infinity) + .background(ColorTheme.Backgrounds.surfaceVariant.color) + .overlay( + arrowView + .frame(width: 120, height: 200) + .padding(.trailing, 40) + .padding(.top, 40) + .allowsHitTesting(false) + .accessibilityHidden(true), + alignment: .topTrailing + ) + .contentShape(Rectangle()) + } + + @ViewBuilder private var arrowView: some View { + Image(.meetingsEmptyArrow) + .resizable() + .renderingMode(.original) + } +} + +#Preview { + MeetingsEmptyStateView() +} diff --git a/WireCalling/Sources/WireCallingUI/WireMeetings/MeetingsListView.swift b/WireCalling/Sources/WireCallingUI/WireMeetings/MeetingsListView.swift new file mode 100644 index 00000000000..4c1489c1fb0 --- /dev/null +++ b/WireCalling/Sources/WireCallingUI/WireMeetings/MeetingsListView.swift @@ -0,0 +1,72 @@ +// +// Wire +// Copyright (C) 2025 Wire Swiss GmbH +// +// 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/. +// + +public import SwiftUI +import WireDesign + +public struct MeetingsListView: View { + + @ObservedObject private var viewModel: MeetingsListViewModel + + public init(viewModel: MeetingsListViewModel) { + self.viewModel = viewModel + } + + public var body: some View { + Group { + if viewModel.hasMeetingsForSelectedTab { + VStack(spacing: 12) { + Picker("", selection: Binding( + get: { viewModel.selectedTab.rawValue }, + set: { viewModel.selectedTab = MeetingsListViewModel.Tab(rawValue: $0) ?? .upcoming } + )) { + ForEach(MeetingsListViewModel.Tab.allCases, id: \.rawValue) { tab in + Text(tab.title).tag(tab.rawValue) + } + } + .pickerStyle(.segmented) + .padding(.horizontal, 16) + .padding(.top, 12) + .padding(.bottom, 10) + .accessibilityIdentifier("meetingsListPicker") + + content + .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .top) + } + } else { + MeetingsEmptyStateView() + } + } + .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .top) + .background(ColorTheme.Backgrounds.background.color) + } + + @ViewBuilder private var content: some View { + switch viewModel.selectedTab { + case .upcoming: + Spacer(minLength: 0) + case .past: + Spacer(minLength: 0) + } + } + +} + +#Preview { + MeetingsListView(viewModel: MeetingsListViewModel(account: AccountUIViewModel(avatarSource: .text("AN"), availability: nil, action: {}))) +} diff --git a/WireCalling/Sources/WireCallingUI/WireMeetings/MeetingsListViewController.swift b/WireCalling/Sources/WireCallingUI/WireMeetings/MeetingsListViewController.swift new file mode 100644 index 00000000000..51e98168a2f --- /dev/null +++ b/WireCalling/Sources/WireCallingUI/WireMeetings/MeetingsListViewController.swift @@ -0,0 +1,138 @@ +// +// Wire +// Copyright (C) 2025 Wire Swiss GmbH +// +// 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/. +// + +public import SwiftUI +import Foundation +import WireAccountImageUI +import WireDesign +import Combine + +public final class MeetingsListViewController: UIViewController { + + private typealias Strings = L10n.Localizable.WireMeetings.List.Actions + + private let viewModel: MeetingsListViewModel + private let hostingController: UIHostingController + private var cancellables = Set() + private var accountWrapperView: AccountUIWrapperView? + + public init(viewModel: MeetingsListViewModel) { + self.viewModel = viewModel + self.hostingController = UIHostingController(rootView: MeetingsListView(viewModel: viewModel)) + super.init(nibName: nil, bundle: nil) + } + + @available(*, unavailable) + required init?(coder: NSCoder) { + fatalError("init(coder:) is not supported") + } + + public override func viewDidLoad() { + super.viewDidLoad() + view.accessibilityViewIsModal = true + addChild(hostingController) + view.addSubview(hostingController.view) + hostingController.didMove(toParent: self) + + hostingController.view.translatesAutoresizingMaskIntoConstraints = false + NSLayoutConstraint.activate([ + hostingController.view.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), + hostingController.view.leadingAnchor.constraint(equalTo: view.leadingAnchor), + hostingController.view.trailingAnchor.constraint(equalTo: view.trailingAnchor), + hostingController.view.bottomAnchor.constraint(equalTo: view.bottomAnchor) + ]) + + setupNavigationBar() + configureNavigationBarAppearance() + viewModel.$account + .receive(on: RunLoop.main) + .sink { [weak self] newAccount in + self?.accountWrapperView?.apply(account: newAccount) + } + .store(in: &cancellables) + } + + public override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + configureNavigationBarAppearance() + } + + // MARK: - Navigation Bar + + private func setupNavigationBar() { + navigationItem.title = L10n.Localizable.WireMeetings.List.title + setupLeftNavigationBarButtonItems() + setupRightNavigationBarButtonItems() + } + + func configureNavigationBarAppearance() { + let appearance = UINavigationBarAppearance() + appearance.configureWithDefaultBackground() + appearance.backgroundColor = ColorTheme.Backgrounds.surface + + navigationController?.navigationBar.standardAppearance = appearance + navigationController?.navigationBar.scrollEdgeAppearance = appearance + navigationController?.navigationBar.compactAppearance = appearance + } + + private func setupRightNavigationBarButtonItems() { + let configuration = UIImage.SymbolConfiguration(font: .systemFont(ofSize: 17)) + let chevron = UIImage(systemName: "chevron.forward", withConfiguration: configuration) + + let meetNow = UIAction(title: Strings.meetNow, image: chevron) { [weak self] _ in + self?.viewModel.meetNowTapped() + } + let schedule = UIAction(title: Strings.scheduleMeeting, image: chevron) { [weak self] _ in + self?.viewModel.scheduleMeetingTapped() + } + + let menu = UIMenu(children: [meetNow, schedule]) + let button = UIButton(type: .system) + button.setImage(UIImage(resource: .videoCall), for: .normal) + button.showsMenuAsPrimaryAction = true + button.menu = menu + button.accessibilityIdentifier = "scheduleMeetingBarButton" + + let item = UIBarButtonItem(customView: button) + navigationItem.rightBarButtonItems = [item] + } + + private func setupLeftNavigationBarButtonItems() { + let stackView = UIStackView() + stackView.spacing = 6 + stackView.axis = .horizontal + stackView.alignment = .center + + let avatar = makeAccountImageView() + stackView.addArrangedSubview(avatar) + accountWrapperView = avatar + + let container = UIBarButtonItem(customView: stackView) + container.accessibilityIdentifier = "accountImageBarButton" + navigationItem.leftBarButtonItems = [container] + } + + private func makeAccountImageView() -> AccountUIWrapperView { + let accountUI = AccountUIWrapperView(viewModel: viewModel.account) + accountUI.isAccessibilityElement = true + accountUI.translatesAutoresizingMaskIntoConstraints = false + accountUI.widthAnchor.constraint(equalToConstant: 28).isActive = true + accountUI.heightAnchor.constraint(equalToConstant: 28).isActive = true + return accountUI + } +} diff --git a/WireCalling/Sources/WireCallingUI/WireMeetings/MeetingsListViewModel.swift b/WireCalling/Sources/WireCallingUI/WireMeetings/MeetingsListViewModel.swift new file mode 100644 index 00000000000..4958ff9695b --- /dev/null +++ b/WireCalling/Sources/WireCallingUI/WireMeetings/MeetingsListViewModel.swift @@ -0,0 +1,69 @@ +// +// Wire +// Copyright (C) 2025 Wire Swiss GmbH +// +// 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/. +// + +public import Foundation + +public final class MeetingsListViewModel: ObservableObject { + + private typealias Strings = L10n.Localizable.WireMeetings.List.Tabs + + enum Tab: Int, CaseIterable { + case upcoming + case past + + var title: String { + switch self { + case .upcoming: Strings.upcoming + case .past: Strings.past + } + } + } + + @Published var selectedTab: Tab = .upcoming + @Published var upcomingMeetings: [Meeting] = [] + @Published var pastMeetings: [Meeting] = [] + + var currentMeetings: [Meeting] { + switch selectedTab { + case .upcoming: upcomingMeetings + case .past: pastMeetings + } + } + + var hasMeetingsForSelectedTab: Bool { !currentMeetings.isEmpty } + @Published var account: AccountUIViewModel + + public init(account: AccountUIViewModel) { + self.account = account + } + + public func updateAccount(_ account: AccountUIViewModel) { + self.account = account + } + + func meetNowTapped() {} + func scheduleMeetingTapped() {} + +} + +package struct Meeting: Identifiable, Hashable { + public let id = UUID() + public let title: String + public let start: Date + public let end: Date +} diff --git a/WireUI/Sources/WireMainNavigationUI/Containers/MainSplitViewController+typealiases.swift b/WireUI/Sources/WireMainNavigationUI/Containers/MainSplitViewController+typealiases.swift index b4023d8efc8..5ea8089bf4b 100644 --- a/WireUI/Sources/WireMainNavigationUI/Containers/MainSplitViewController+typealiases.swift +++ b/WireUI/Sources/WireMainNavigationUI/Containers/MainSplitViewController+typealiases.swift @@ -23,6 +23,7 @@ public extension MainSplitViewController { typealias ConversationListUI = TabController.ConversationListUI typealias ArchiveUI = TabController.ArchiveUI typealias SettingsUI = TabController.SettingsUI + typealias MeetingsUI = TabController.MeetingsUI typealias ConversationUI = TabController.ConversationUI typealias SettingsContentUI = UIViewController diff --git a/WireUI/Sources/WireMainNavigationUI/Containers/MainSplitViewController.swift b/WireUI/Sources/WireMainNavigationUI/Containers/MainSplitViewController.swift index 792f5b283a2..250ec2efab8 100644 --- a/WireUI/Sources/WireMainNavigationUI/Containers/MainSplitViewController.swift +++ b/WireUI/Sources/WireMainNavigationUI/Containers/MainSplitViewController.swift @@ -46,6 +46,11 @@ public final class MainSplitViewController: UISplitViewC set { setArchiveUI(newValue, animated: false) } } + public var meetingsUI: MeetingsUI? { + get { _meetingsUI } + set { setMeetingsUI(newValue, animated: false) } + } + public var settingsUI: SettingsUI? { get { _settingsUI } set { setSettingsUI(newValue, animated: false) } @@ -79,6 +84,7 @@ public final class MainSplitViewController: UISplitViewC private weak var _conversationListUI: ConversationListUI? private weak var _archiveUI: ArchiveUI? + private weak var _meetingsUI: MeetingsUI? private weak var _settingsUI: SettingsUI? private weak var _conversationUI: ConversationUI? @@ -170,6 +176,14 @@ public final class MainSplitViewController: UISplitViewC splitLayoutContainer.primaryNavigationController.view.layoutIfNeeded() } + private func setMeetingsUI(_ meetingsUI: MeetingsUI?, animated: Bool) { + _meetingsUI = meetingsUI + + let viewControllers = [meetingsUI].compactMap(\.self) + splitLayoutContainer.primaryNavigationController.setViewControllers(viewControllers, animated: animated) + splitLayoutContainer.primaryNavigationController.view.layoutIfNeeded() + } + private func setSettingsUI(_ settingsUI: SettingsUI?, animated: Bool) { _settingsUI = settingsUI diff --git a/WireUI/Sources/WireMainNavigationUI/Containers/MainTabBarController.swift b/WireUI/Sources/WireMainNavigationUI/Containers/MainTabBarController.swift index 56bbda4e4d2..59de6f0d53d 100644 --- a/WireUI/Sources/WireMainNavigationUI/Containers/MainTabBarController.swift +++ b/WireUI/Sources/WireMainNavigationUI/Containers/MainTabBarController.swift @@ -31,6 +31,7 @@ public final class MainTabBarController< public typealias ArchiveUI = UIViewController public typealias SettingsUI = UIViewController + public typealias MeetingsUI = UIViewController // MARK: - Public Properties @@ -44,6 +45,11 @@ public final class MainTabBarController< set { setArchiveUI(newValue, animated: false) } } + public var meetingsUI: MeetingsUI? { + get { _meetingsUI } + set { setMeetingsUI(newValue, animated: false) } + } + public var settingsUI: SettingsUI? { get { _settingsUI } set { setSettingsUI(newValue, animated: false) } @@ -68,17 +74,23 @@ public final class MainTabBarController< private weak var conversationListNavigationController: UINavigationController! private weak var archiveNavigationController: UINavigationController! + private weak var meetingsNavigationController: UINavigationController! private weak var settingsNavigationController: UINavigationController! private weak var _conversationListUI: ConversationListUI? private weak var _archiveUI: ArchiveUI? + private weak var _meetingsUI: MeetingsUI? private weak var _settingsUI: SettingsUI? private weak var _conversationUI: ConversationUI? private weak var _settingsContentUI: UIViewController? + /// We should use DeveloperFlag 'wireMeetings' after moving it to WireFoundation: + /// https://wearezeta.atlassian.net/browse/WPB-19065 + private var showMeetings: Bool // MARK: - Life Cycle - public required init() { + public init(showMeetings: Bool) { + self.showMeetings = showMeetings super.init(nibName: nil, bundle: nil) setupTabs() setupAppearance() @@ -98,16 +110,25 @@ public final class MainTabBarController< archiveNavigationController.navigationBar.isTranslucent = false self.archiveNavigationController = archiveNavigationController + let meetingsNavigationController = UINavigationController() + meetingsNavigationController.navigationBar.isTranslucent = false + self.meetingsNavigationController = meetingsNavigationController + let settingsNavigationController = UINavigationController() settingsNavigationController.navigationBar.isTranslucent = false self.settingsNavigationController = settingsNavigationController - viewControllers = [ + var tabs: [UIViewController] = [ conversationListNavigationController, archiveNavigationController, settingsNavigationController ] + if showMeetings { + tabs.insert(meetingsNavigationController, at: 2) + } + setViewControllers(tabs, animated: false) + for content in MainTabBarControllerContent.allCases { switch content { case .conversations: @@ -148,6 +169,25 @@ public final class MainTabBarController< ) archiveNavigationController.tabBarItem = tabBarItem + case .meetings: + let tabBarItem = UITabBarItem( + title: String(localized: "tabBar.meetings.title", bundle: .module), + image: .init(resource: .videoCall), + selectedImage: .init(resource: .videoCallFilled) + ) + tabBarItem.accessibilityIdentifier = "bottomBarMeetingsButton" + tabBarItem.accessibilityLabel = String( + localized: "tabBar.meetings.description", + table: "Accessibility", + bundle: .module + ) + tabBarItem.accessibilityHint = String( + localized: "tabBar.meetings.hint", + table: "Accessibility", + bundle: .module + ) + meetingsNavigationController.tabBarItem = tabBarItem + case .settings: let tabBarItem = UITabBarItem( title: String(localized: "tabBar.settings.title", bundle: .module), @@ -209,6 +249,14 @@ public final class MainTabBarController< archiveNavigationController.view.layoutIfNeeded() } + private func setMeetingsUI(_ meetingsUI: MeetingsUI?, animated: Bool) { + _meetingsUI = meetingsUI + + let viewControllers = [meetingsUI].compactMap(\.self) + meetingsNavigationController.setViewControllers(viewControllers, animated: animated) + meetingsNavigationController.view.layoutIfNeeded() + } + private func setSettingsUI(_ settingsUI: SettingsUI?, animated: Bool) { _settingsUI = settingsUI diff --git a/WireUI/Sources/WireMainNavigationUI/Coordinator/AnyMainCoordinator.swift b/WireUI/Sources/WireMainNavigationUI/Coordinator/AnyMainCoordinator.swift index d877e93b2bd..23a6c3b06cd 100644 --- a/WireUI/Sources/WireMainNavigationUI/Coordinator/AnyMainCoordinator.swift +++ b/WireUI/Sources/WireMainNavigationUI/Coordinator/AnyMainCoordinator.swift @@ -26,12 +26,14 @@ public final class AnyMainCoordinator Void private let _applyConversationFilter: @MainActor (_ conversationFilter: ConversationFilter?) -> Void private let _showArchive: @MainActor () async -> Void + private let _showMeetings: @MainActor () async -> Void private let _showSettings: @MainActor () async -> Void private let _showConversation: @MainActor ( _ conversation: ConversationModel, _ message: ConversationMessageModel? ) async -> Void private let _hideConversation: @MainActor () -> Void + private let _hideMeetings: @MainActor () -> Void private let _showSettingsContent: @MainActor (_ topLevelMenuItem: SettingsTopLevelMenuItem) -> Void private let _hideSettingsContent: @MainActor () -> Void private let _presentViewController: @MainActor (_ viewController: UIViewController) async -> Void @@ -54,12 +56,18 @@ public final class AnyMainCoordinator: NSObject, MainCoordinatorProto } } + private var meetingsUI: TabBarController.MeetingsUI! { + switch mainSplitViewState { + case .collapsed: tabBarController.meetingsUI + case .expanded: splitViewController.meetingsUI + } + } + private var settingsUI: TabBarController.SettingsUI! { switch mainSplitViewState { case .collapsed: tabBarController.settingsUI @@ -190,6 +197,10 @@ public final class MainCoordinator: NSObject, MainCoordinatorProto showSettingsContent(.init(.account)) // TODO: [WPB-11347] make the selection visible } + public func showMeetings() async { + // TODO: [WPB-20272]: add list of meetings + } + public func showConversation( conversation: ConversationModel, message: ConversationMessageModel? @@ -252,6 +263,8 @@ public final class MainCoordinator: NSObject, MainCoordinatorProto splitViewController.settingsContentUI = nil } + public func hideMeetings() {} + public func presentViewController(_ viewController: UIViewController) async { if mainSplitViewState == .expanded, splitViewController.splitBehavior == .overlay { splitViewController.hideSidebar() @@ -409,6 +422,9 @@ public final class MainCoordinator: NSObject, MainCoordinatorProto case .archive: sidebar.selectedMenuItem = .init(.archive) + case .meetings: + sidebar.selectedMenuItem = .init(.meetings) + case .settings: sidebar.selectedMenuItem = .init(.settings) } diff --git a/WireUI/Sources/WireMainNavigationUI/Models/MainSidebarMenuItem.swift b/WireUI/Sources/WireMainNavigationUI/Models/MainSidebarMenuItem.swift index 389e6f668ad..65f86382eb1 100644 --- a/WireUI/Sources/WireMainNavigationUI/Models/MainSidebarMenuItem.swift +++ b/WireUI/Sources/WireMainNavigationUI/Models/MainSidebarMenuItem.swift @@ -31,6 +31,7 @@ public enum MainSidebarMenuItem: Sendable, Equatable { case drafts case archive case folders + case meetings // bottom case settings } diff --git a/WireUI/Sources/WireMainNavigationUI/Models/MainTabBarControllerContent.swift b/WireUI/Sources/WireMainNavigationUI/Models/MainTabBarControllerContent.swift index 565e1bdcb2e..1e8cc2e2550 100644 --- a/WireUI/Sources/WireMainNavigationUI/Models/MainTabBarControllerContent.swift +++ b/WireUI/Sources/WireMainNavigationUI/Models/MainTabBarControllerContent.swift @@ -22,4 +22,5 @@ public enum MainTabBarControllerContent: Int, CaseIterable { case conversations case archive case settings + case meetings } diff --git a/WireUI/Sources/WireMainNavigationUI/Preview/MainSplitViewControllerPreview.swift b/WireUI/Sources/WireMainNavigationUI/Preview/MainSplitViewControllerPreview.swift index 77111e2f316..32ca5e72280 100644 --- a/WireUI/Sources/WireMainNavigationUI/Preview/MainSplitViewControllerPreview.swift +++ b/WireUI/Sources/WireMainNavigationUI/Preview/MainSplitViewControllerPreview.swift @@ -23,7 +23,7 @@ func MainSplitViewControllerPreview() -> UISplitViewController { let splitViewController = MainSplitViewController( sidebar: PreviewSidebarViewController("sidebar"), noConversationPlaceholder: UIHostingController(rootView: Text(verbatim: "no conversation placeholder")), - tabController: .init() + tabController: .init(showMeetings: false) ) splitViewController.conversationListUI = PreviewConversationListViewController("conversation list") return splitViewController diff --git a/WireUI/Sources/WireMainNavigationUI/Preview/MainTabBarControllerPreview.swift b/WireUI/Sources/WireMainNavigationUI/Preview/MainTabBarControllerPreview.swift index d23534f2dd2..941a66c46b0 100644 --- a/WireUI/Sources/WireMainNavigationUI/Preview/MainTabBarControllerPreview.swift +++ b/WireUI/Sources/WireMainNavigationUI/Preview/MainTabBarControllerPreview.swift @@ -20,7 +20,7 @@ import SwiftUI @MainActor func MainTabBarControllerPreview() -> some MainTabBarControllerProtocol { - let tabBarController = PreviewTabBarController() + let tabBarController = PreviewTabBarController(showMeetings: false) tabBarController.conversationListUI = .init("conversationList") tabBarController.archiveUI = PlaceholderViewController() tabBarController.settingsUI = .init() diff --git a/WireUI/Sources/WireMainNavigationUI/Protocols/Containers/MainContainerViewController.swift b/WireUI/Sources/WireMainNavigationUI/Protocols/Containers/MainContainerViewController.swift index 36a8e2816bc..646f646f719 100644 --- a/WireUI/Sources/WireMainNavigationUI/Protocols/Containers/MainContainerViewController.swift +++ b/WireUI/Sources/WireMainNavigationUI/Protocols/Containers/MainContainerViewController.swift @@ -25,12 +25,14 @@ public protocol MainContainerViewControllerProtocol: UIViewController { associatedtype ConversationListUI: MainConversationListUIProtocol associatedtype ArchiveUI: UIViewController associatedtype SettingsUI: UIViewController + associatedtype MeetingsUI: UIViewController associatedtype ConversationUI: MainConversationUIProtocol // These three properties represent the tabs of the main tab bar controller. var conversationListUI: ConversationListUI? { get set } var archiveUI: ArchiveUI? { get set } + var meetingsUI: MeetingsUI? { get set } var settingsUI: SettingsUI? { get set } // These two represent the content, which will be pushed on the three main screens. diff --git a/WireUI/Sources/WireMainNavigationUI/Protocols/Containers/MainSplitViewControllerProtocol.swift b/WireUI/Sources/WireMainNavigationUI/Protocols/Containers/MainSplitViewControllerProtocol.swift index 95f37d63df5..ec37a0176cf 100644 --- a/WireUI/Sources/WireMainNavigationUI/Protocols/Containers/MainSplitViewControllerProtocol.swift +++ b/WireUI/Sources/WireMainNavigationUI/Protocols/Containers/MainSplitViewControllerProtocol.swift @@ -26,6 +26,7 @@ public protocol MainSplitViewControllerProtocol: UISplitViewController, MainCont TabBarController.ConversationListUI == ConversationListUI, TabBarController.ConversationUI == ConversationUI, TabBarController.ArchiveUI == ArchiveUI, + TabBarController.MeetingsUI == MeetingsUI, TabBarController.SettingsUI == SettingsUI /// Contains the reference to the view controller shown in the primary column. diff --git a/WireUI/Sources/WireMainNavigationUI/Protocols/Coordinator/MainCoordinatorProtocol.swift b/WireUI/Sources/WireMainNavigationUI/Protocols/Coordinator/MainCoordinatorProtocol.swift index b7e33b496dd..3e14a36da0b 100644 --- a/WireUI/Sources/WireMainNavigationUI/Protocols/Coordinator/MainCoordinatorProtocol.swift +++ b/WireUI/Sources/WireMainNavigationUI/Protocols/Coordinator/MainCoordinatorProtocol.swift @@ -35,12 +35,16 @@ public protocol MainCoordinatorProtocol: AnyObject { func showArchive() async @MainActor func showSettings() async + @MainActor + func showMeetings() async @MainActor func showConversation(conversation: ConversationModel, message: ConversationMessageModel?) async /// This method will be called by the custom back button in the conversation content screen. @MainActor func hideConversation() + @MainActor + func hideMeetings() @MainActor func showSettingsContent(_ topLevelMenuItem: SettingsTopLevelMenuItem) diff --git a/WireUI/Sources/WireMainNavigationUI/Resources/Images.xcassets/Contents.json b/WireUI/Sources/WireMainNavigationUI/Resources/Images.xcassets/Contents.json new file mode 100644 index 00000000000..73c00596a7f --- /dev/null +++ b/WireUI/Sources/WireMainNavigationUI/Resources/Images.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/WireUI/Sources/WireMainNavigationUI/Resources/Images.xcassets/VideoCall.imageset/Contents.json b/WireUI/Sources/WireMainNavigationUI/Resources/Images.xcassets/VideoCall.imageset/Contents.json new file mode 100644 index 00000000000..e388c79f4e0 --- /dev/null +++ b/WireUI/Sources/WireMainNavigationUI/Resources/Images.xcassets/VideoCall.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "VideoCall.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "template" + } +} diff --git a/WireUI/Sources/WireMainNavigationUI/Resources/Images.xcassets/VideoCall.imageset/VideoCall.svg b/WireUI/Sources/WireMainNavigationUI/Resources/Images.xcassets/VideoCall.imageset/VideoCall.svg new file mode 100644 index 00000000000..08d70c6877f --- /dev/null +++ b/WireUI/Sources/WireMainNavigationUI/Resources/Images.xcassets/VideoCall.imageset/VideoCall.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/WireUI/Sources/WireMainNavigationUI/Resources/Images.xcassets/VideoCallFilled.imageset/Contents.json b/WireUI/Sources/WireMainNavigationUI/Resources/Images.xcassets/VideoCallFilled.imageset/Contents.json new file mode 100644 index 00000000000..af3b035e2fe --- /dev/null +++ b/WireUI/Sources/WireMainNavigationUI/Resources/Images.xcassets/VideoCallFilled.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "VideoCallFilled.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "template" + } +} diff --git a/WireUI/Sources/WireMainNavigationUI/Resources/Images.xcassets/VideoCallFilled.imageset/VideoCallFilled.svg b/WireUI/Sources/WireMainNavigationUI/Resources/Images.xcassets/VideoCallFilled.imageset/VideoCallFilled.svg new file mode 100644 index 00000000000..ce8f6a70196 --- /dev/null +++ b/WireUI/Sources/WireMainNavigationUI/Resources/Images.xcassets/VideoCallFilled.imageset/VideoCallFilled.svg @@ -0,0 +1,4 @@ + + + + diff --git a/WireUI/Sources/WireMainNavigationUI/Resources/Localization/Accessibility.xcstrings b/WireUI/Sources/WireMainNavigationUI/Resources/Localization/Accessibility.xcstrings index f2b02e5e6f9..ec659dae2e1 100644 --- a/WireUI/Sources/WireMainNavigationUI/Resources/Localization/Accessibility.xcstrings +++ b/WireUI/Sources/WireMainNavigationUI/Resources/Localization/Accessibility.xcstrings @@ -497,6 +497,28 @@ } } }, + "tabBar.meetings.description" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Meetings" + } + } + } + }, + "tabBar.meetings.hint" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "List of meetings" + } + } + } + }, "tabBar.settings.description" : { "localizations" : { "ar" : { @@ -747,4 +769,4 @@ } }, "version" : "1.0" -} +} \ No newline at end of file diff --git a/WireUI/Sources/WireMainNavigationUI/Resources/Localization/Localizable.xcstrings b/WireUI/Sources/WireMainNavigationUI/Resources/Localization/Localizable.xcstrings index b01fa011906..cd8aaa4685f 100644 --- a/WireUI/Sources/WireMainNavigationUI/Resources/Localization/Localizable.xcstrings +++ b/WireUI/Sources/WireMainNavigationUI/Resources/Localization/Localizable.xcstrings @@ -249,6 +249,17 @@ } } }, + "tabBar.meetings.title" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Meetings" + } + } + } + }, "tabBar.settings.title" : { "localizations" : { "ar" : { @@ -375,4 +386,4 @@ } }, "version" : "1.0" -} +} \ No newline at end of file diff --git a/WireUI/Sources/WireSidebarUI/Models/SidebarModel.swift b/WireUI/Sources/WireSidebarUI/Models/SidebarModel.swift index a6c02be1059..dd6b38a673a 100644 --- a/WireUI/Sources/WireSidebarUI/Models/SidebarModel.swift +++ b/WireUI/Sources/WireSidebarUI/Models/SidebarModel.swift @@ -41,6 +41,7 @@ final class SidebarModel: ObservableObject { } @Published var showUnreadFilters: Bool = false + @Published var showMeetings: Bool = false let accountImageAction: () -> Void let menuItemAction: (_ selectedMenuItem: SidebarSelectableMenuItem) -> Void diff --git a/WireUI/Sources/WireSidebarUI/Models/SidebarSelectableMenuItem.swift b/WireUI/Sources/WireSidebarUI/Models/SidebarSelectableMenuItem.swift index 2884e9bf1c4..e43f7d7003d 100644 --- a/WireUI/Sources/WireSidebarUI/Models/SidebarSelectableMenuItem.swift +++ b/WireUI/Sources/WireSidebarUI/Models/SidebarSelectableMenuItem.swift @@ -30,6 +30,7 @@ public enum SidebarSelectableMenuItem: Comparable, Sendable, Hashable { case replies case drafts case folders + case meetings // archived conversations case archive // bottom diff --git a/WireUI/Sources/WireSidebarUI/Resources/Localization/en.lproj/Localizable.strings b/WireUI/Sources/WireSidebarUI/Resources/Localization/en.lproj/Localizable.strings index 21cbacf06a9..9f83e2797b9 100644 --- a/WireUI/Sources/WireSidebarUI/Resources/Localization/en.lproj/Localizable.strings +++ b/WireUI/Sources/WireSidebarUI/Resources/Localization/en.lproj/Localizable.strings @@ -31,6 +31,9 @@ "sidebar.conversation_filter.folders.title" = "Folders"; "sidebar.conversation_filter.archived.title" = "Archive"; +"sidebar.meetings.title" = "Meetings"; +"sidebar.meetings.all_meetings.title" = "All Meetings"; + "sidebar.contacts.title" = "Contacts"; "sidebar.contacts.connect.title" = "Connect"; diff --git a/WireUI/Sources/WireSidebarUI/Views/Preview/SidebarPreview.swift b/WireUI/Sources/WireSidebarUI/Views/Preview/SidebarPreview.swift index d7994130ace..ca874723cd4 100644 --- a/WireUI/Sources/WireSidebarUI/Views/Preview/SidebarPreview.swift +++ b/WireUI/Sources/WireSidebarUI/Views/Preview/SidebarPreview.swift @@ -49,6 +49,7 @@ struct SidebarPreview: View { accountInfo: accountInfo, selectedMenuItem: $selectedMenuItem, showUnreadFilters: false, + showMeetings: false, accountImageAction: {}, foldersAction: { _ in }, supportAction: {}, diff --git a/WireUI/Sources/WireSidebarUI/Views/SidebarView.swift b/WireUI/Sources/WireSidebarUI/Views/SidebarView.swift index bb1b48b1c93..0c5ba53e34f 100644 --- a/WireUI/Sources/WireSidebarUI/Views/SidebarView.swift +++ b/WireUI/Sources/WireSidebarUI/Views/SidebarView.swift @@ -27,6 +27,7 @@ public struct SidebarView: public var accountInfo: SidebarAccountInfo? @Binding public var selectedMenuItem: SidebarSelectableMenuItem public var showUnreadFilters: Bool + public var showMeetings: Bool private(set) var accountImageAction: () -> Void private(set) var foldersAction: (CGRect) -> Void @@ -44,6 +45,7 @@ public struct SidebarView: accountInfo: SidebarAccountInfo, selectedMenuItem: Binding, showUnreadFilters: Bool, + showMeetings: Bool, accountImageAction: @escaping () -> Void, foldersAction: @escaping (_ buttonFrame: CGRect) -> Void, supportAction: @escaping () -> Void, @@ -53,6 +55,7 @@ public struct SidebarView: self.accountInfo = accountInfo _selectedMenuItem = selectedMenuItem self.showUnreadFilters = showUnreadFilters + self.showMeetings = showMeetings self.accountImageAction = accountImageAction self.foldersAction = foldersAction self.supportAction = supportAction @@ -137,6 +140,12 @@ public struct SidebarView: // Additional filters selectableMenuItem(.folders) selectableMenuItem(.archive) + + // Meetings + if showMeetings { + menuItemHeader(Strings.Meetings.title, addTopPadding: false) + selectableMenuItem(.meetings) + } } .padding(.horizontal, 16) } @@ -262,6 +271,11 @@ public struct SidebarView: icon = "archivebox" accessibilityLabel = Text(Strings.ConversationFilter.Archived.title) + case .meetings: + text = Text(Strings.Meetings.AllMeetings.title) + icon = "video" + accessibilityLabel = Text(Strings.Meetings.AllMeetings.title) + case .settings: text = Text(Strings.Settings.title) icon = "gearshape" diff --git a/WireUI/Sources/WireSidebarUI/Views/SidebarViewController.swift b/WireUI/Sources/WireSidebarUI/Views/SidebarViewController.swift index a007a543590..0b3abe8afc6 100644 --- a/WireUI/Sources/WireSidebarUI/Views/SidebarViewController.swift +++ b/WireUI/Sources/WireSidebarUI/Views/SidebarViewController.swift @@ -94,6 +94,11 @@ public final class SidebarViewController: UIViewController { set { model.showUnreadFilters = newValue } } + public var showMeetings: Bool { + get { model.showMeetings } + set { model.showMeetings = newValue } + } + // MARK: - Private Properties private var model: SidebarModel! @@ -176,6 +181,7 @@ private struct SidebarAdapter