Skip to content

Commit 3d3868f

Browse files
authored
integrate AlertToast for notification (#19)
1 parent 77ec5b9 commit 3d3868f

18 files changed

+172
-11
lines changed

.gitmodules

+3
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,6 @@
1919
[submodule "data/rime-stroke"]
2020
path = data/rime-stroke
2121
url = https://github.com/rime/rime-stroke
22+
[submodule "deps/AlertToast"]
23+
path = deps/AlertToast
24+
url = https://github.com/fcitx-contrib/AlertToast

CMakeLists.txt

+3
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ find_package(LibIntl)
4141
set(fmt_DIR "${PREBUILDER_LIB_DIR}/cmake/fmt")
4242
find_package(fmt)
4343

44+
add_subdirectory(deps)
45+
4446
option(ENABLE_TEST "" OFF)
4547
option(ENABLE_COVERAGE "" OFF)
4648
option(ENABLE_ENCHANT "" OFF)
@@ -63,6 +65,7 @@ add_subdirectory(fcitx5)
6365

6466
add_subdirectory(protocol)
6567
add_subdirectory(iosfrontend)
68+
add_subdirectory(iosnotifications)
6669
add_subdirectory(uipanel)
6770
add_subdirectory(ipc)
6871

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ You can also use `Cmd+Shift+B` in VSCode to execute a task.
3333
```sh
3434
xcrun simctl list devices
3535
xcrun simctl boot UUID
36+
open /Applications/Xcode.app/Contents/Developer/Applications/Simulator.app
3637
xcrun simctl install booted build/src/Debug-iphonesimulator/Fcitx5.app
3738
```
3839
After the first time you execute `xcrun simctl install`,

common/CMakeLists.txt

+3
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
11
add_library(FcitxCommon common.cpp)
2+
target_include_directories(FcitxCommon PRIVATE
3+
"${PROJECT_SOURCE_DIR}/fcitx5/src/modules/notifications"
4+
)
25
target_link_libraries(FcitxCommon Fcitx5::Core)

common/common.cpp

+10-6
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include "../engines/fcitx5-rime/src/rimeengine.h"
44
#include "../fcitx5/src/modules/spell/spell.h"
55
#include "../iosfrontend/iosfrontend.h"
6+
#include "../iosnotifications/iosnotifications.h"
67
#include "../uipanel/uipanel.h"
78
#include "nativestreambuf.h"
89
#include <filesystem>
@@ -19,16 +20,19 @@ fcitx::RimeEngineFactory RimeFactory;
1920

2021
namespace fs = std::filesystem;
2122

22-
fcitx::IosFrontendFactory IosFrontendFactory;
23-
fcitx::UIPanelFactory UIPanelFactory;
23+
static fcitx::IosFrontendFactory IosFrontendFactory;
24+
static fcitx::IosNotificationsFactory IosNotificationsFactory;
25+
static fcitx::UIPanelFactory UIPanelFactory;
2426

25-
fcitx::StaticAddonRegistry addons = {
27+
static fcitx::StaticAddonRegistry addons = {
2628
#ifdef HALLELUJAH
2729
std::make_pair<std::string, fcitx::AddonFactory *>("spell",
2830
&SpellModuleFactory),
2931
#endif
3032
std::make_pair<std::string, fcitx::AddonFactory *>("iosfrontend",
3133
&IosFrontendFactory),
34+
std::make_pair<std::string, fcitx::AddonFactory *>(
35+
"notifications", &IosNotificationsFactory),
3236
std::make_pair<std::string, fcitx::AddonFactory *>("uipanel",
3337
&UIPanelFactory),
3438
#ifdef HALLELUJAH
@@ -43,10 +47,10 @@ fcitx::StaticAddonRegistry addons = {
4347
std::unique_ptr<fcitx::Instance> instance;
4448
std::unique_ptr<fcitx::EventDispatcher> dispatcher;
4549

46-
native_streambuf log_streambuf;
47-
std::ostream stream(&log_streambuf);
50+
static native_streambuf log_streambuf;
51+
static std::ostream stream(&log_streambuf);
4852

49-
std::thread fcitx_thread;
53+
static std::thread fcitx_thread;
5054

5155
void setupLog() {
5256
fcitx::Log::setLogStream(stream);

deps/AlertToast

Submodule AlertToast added at 6e902e1

deps/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
add_subdirectory(AlertToast)

iosnotifications/CMakeLists.txt

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
add_library(NotifySwift STATIC notify.swift toast.swift)
2+
set_target_properties(NotifySwift PROPERTIES Swift_MODULE_NAME NotifySwift)
3+
target_compile_options(NotifySwift PUBLIC "$<$<COMPILE_LANGUAGE:Swift>:-cxx-interoperability-mode=default>")
4+
5+
_swift_generate_cxx_header(
6+
NotifySwift
7+
"${CMAKE_CURRENT_BINARY_DIR}/include/notify-swift.h"
8+
SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/notify.swift"
9+
SEARCH_PATHS "${CMAKE_CURRENT_SOURCE_DIR}"
10+
)
11+
12+
add_library(iosnotifications iosnotifications.cpp)
13+
add_dependencies(iosnotifications NotifySwift)
14+
target_include_directories(iosnotifications PUBLIC
15+
"${CMAKE_CURRENT_BINARY_DIR}/include"
16+
)
17+
target_link_libraries(iosnotifications Fcitx5::Core Fcitx5::Module::Notifications)
18+
19+
configure_file(notifications.conf.in.in notifications.conf.in @ONLY)
20+
fcitx5_translate_desktop_file(${CMAKE_CURRENT_BINARY_DIR}/notifications.conf.in notifications.conf)
21+
22+
add_custom_command(
23+
TARGET iosnotifications
24+
POST_BUILD COMMAND /bin/sh -c
25+
\"
26+
${CMAKE_COMMAND} -E copy
27+
${CMAKE_CURRENT_BINARY_DIR}/notifications.conf
28+
${PROJECT_BINARY_DIR}/keyboard/$<CONFIG>${CMAKE_XCODE_EFFECTIVE_PLATFORMS}/keyboard.appex/share/fcitx5/addon/notifications.conf
29+
\"
30+
)

iosnotifications/iosnotifications.cpp

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#include "iosnotifications.h"
2+
#include "notify-swift.h"
3+
4+
namespace fcitx {
5+
Notifications::Notifications(Instance *instance) {}
6+
7+
uint32_t Notifications::sendNotification(
8+
const std::string &appName, uint32_t replaceId, const std::string &appIcon,
9+
const std::string &summary, const std::string &body,
10+
const std::vector<std::string> &actions, int32_t timeout,
11+
NotificationActionCallback actionCallback,
12+
NotificationClosedCallback closedCallback) {
13+
14+
FCITX_INFO() << "sendNotification " << body;
15+
return 0;
16+
}
17+
18+
void Notifications::showTip(const std::string &tipId,
19+
const std::string &appName,
20+
const std::string &appIcon,
21+
const std::string &summary, const std::string &body,
22+
int32_t timeout) {
23+
NotifySwift::showTip(body, timeout);
24+
}
25+
26+
void Notifications::closeNotification(uint64_t internalId) {
27+
FCITX_INFO() << "closeNotification " << internalId;
28+
}
29+
} // namespace fcitx

iosnotifications/iosnotifications.h

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#pragma once
2+
3+
#include <fcitx/addonfactory.h>
4+
#include <fcitx/addoninstance.h>
5+
#include <fcitx/addonmanager.h>
6+
#include <fcitx/instance.h>
7+
#include <notifications_public.h>
8+
9+
namespace fcitx {
10+
class Notifications final : public AddonInstance {
11+
public:
12+
Notifications(Instance *instance);
13+
~Notifications() = default;
14+
uint32_t sendNotification(const std::string &appName, uint32_t replaceId,
15+
const std::string &appIcon,
16+
const std::string &summary,
17+
const std::string &body,
18+
const std::vector<std::string> &actions,
19+
int32_t timeout,
20+
NotificationActionCallback actionCallback,
21+
NotificationClosedCallback closedCallback);
22+
void showTip(const std::string &tipId, const std::string &appName,
23+
const std::string &appIcon, const std::string &summary,
24+
const std::string &body, int32_t timeout);
25+
26+
void closeNotification(uint64_t internalId);
27+
28+
private:
29+
FCITX_ADDON_EXPORT_FUNCTION(Notifications, sendNotification);
30+
FCITX_ADDON_EXPORT_FUNCTION(Notifications, showTip);
31+
FCITX_ADDON_EXPORT_FUNCTION(Notifications, closeNotification);
32+
};
33+
34+
class IosNotificationsFactory : public AddonFactory {
35+
AddonInstance *create(AddonManager *manager) override {
36+
return new Notifications(manager->instance());
37+
}
38+
};
39+
} // namespace fcitx
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
[Addon]
2+
Name=iOS Notification
3+
Type=StaticLibrary
4+
Library=libiosnotifications
5+
Category=Module
6+
Version=@PROJECT_VERSION@
7+
Configurable=True

iosnotifications/notify.swift

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
public func showTip(_ body: String, _ timeout: Int32) {
2+
guard let showToastCallback = showToastCallback else {
3+
return
4+
}
5+
showToastCallback(body, timeout)
6+
}

iosnotifications/toast.swift

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
var showToastCallback: ((String, Int32) -> Void)?
2+
3+
public func setShowToastCallback(_ callback: @escaping (String, Int32) -> Void) {
4+
showToastCallback = callback
5+
}

keyboard/CMakeLists.txt

+2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ target_link_libraries(keyboard PRIVATE
2121
SwiftFrontend
2222
KeyboardUI
2323
uipanel
24+
iosnotifications
25+
NotifySwift
2426
FcitxIpc
2527
FcitxCommon
2628
${ADDONS}

scripts/format.sh

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
find common src keyboard iosfrontend uipanel -name '*.cpp' -o -name '*.h' | xargs clang-format -i
2-
swift-format format --in-place $(find src keyboard iosfrontend uipanel protocol ipc -name '*.swift')
1+
find common src keyboard iosfrontend iosnotifications uipanel -name '*.cpp' -o -name '*.h' | xargs clang-format -i
2+
swift-format format --in-place $(find src keyboard iosfrontend iosnotifications uipanel protocol ipc -name '*.swift')

scripts/lint.sh

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
set -e
22

3-
find common src keyboard iosfrontend uipanel -name '*.cpp' -o -name '*.h' | xargs clang-format -Werror --dry-run
4-
swift-format lint -rs src keyboard iosfrontend uipanel protocol ipc
3+
find common src keyboard iosfrontend iosnotifications uipanel -name '*.cpp' -o -name '*.h' | xargs clang-format -Werror --dry-run
4+
swift-format lint -rs src keyboard iosfrontend iosnotifications uipanel protocol ipc

src/CMakeLists.txt

+8-1
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,20 @@ add_executable(
99
fcitx.cpp
1010
)
1111

12-
target_include_directories(${BUNDLE_NAME} PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}")
12+
target_include_directories(${BUNDLE_NAME} PRIVATE
13+
"${CMAKE_CURRENT_SOURCE_DIR}"
14+
"${PROJECT_BINARY_DIR}/iosnotifications/$<CONFIG>${CMAKE_XCODE_EFFECTIVE_PLATFORMS}"
15+
"${PROJECT_BINARY_DIR}/deps/AlertToast/$<CONFIG>${CMAKE_XCODE_EFFECTIVE_PLATFORMS}"
16+
)
1317

1418
target_link_libraries(${BUNDLE_NAME} PRIVATE
19+
AlertToast
1520
iosfrontend
1621
SwiftFrontend
1722
KeyboardUI
1823
uipanel
24+
iosnotifications
25+
NotifySwift
1926
FcitxIpc
2027
FcitxCommon
2128
${ADDONS}

src/ContentView.swift

+20
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1+
import AlertToast
12
import Fcitx
3+
import NotifySwift
24
import SwiftUI
35

46
private class ViewModel: ObservableObject {
@@ -8,6 +10,9 @@ private class ViewModel: ObservableObject {
810
struct ContentView: View {
911
@Environment(\.scenePhase) private var scenePhase
1012
@ObservedObject private var viewModel = ViewModel()
13+
@State private var showToast = false
14+
@State private var duration = 3.0
15+
@State private var message = ""
1116

1217
func handleURL(_ url: URL) {
1318
viewModel.url = url
@@ -24,10 +29,25 @@ struct ContentView: View {
2429
}
2530
}
2631
.padding()
32+
.toast(isPresenting: $showToast, duration: duration) {
33+
AlertToast(
34+
displayMode: .alert, type: .regular,
35+
subTitle: message,
36+
style: AlertToast.AlertStyle.style(
37+
subTitleFont: Font.system(size: 20)
38+
))
39+
}
2740
.onAppear {
2841
// The stupid iOS doesn't show empty directory in Files.app.
2942
try? "".write(
3043
to: documents.appendingPathComponent("placeholder"), atomically: true, encoding: .utf8)
44+
setShowToastCallback({ message, duration in
45+
DispatchQueue.main.async {
46+
self.duration = Double(duration) / 1000.0
47+
self.message = message
48+
showToast = true
49+
}
50+
})
3151
}
3252
.onChange(of: scenePhase) { newPhase in
3353
if newPhase == .active {

0 commit comments

Comments
 (0)