Skip to content

Commit

Permalink
refactor: fixed DWORD ipc_id (combination of pid and order_id) instea…
Browse files Browse the repository at this point in the history
…d of RimeSessionId

build: build 32/64 bit WeaselServer and WeaselDeployer, default x64 build in `output`, Win32 build in `output\Win32`
update WeaselServerApp.h: de-warning for 64 bit build.
chore:TestWeaselIPC with a lowercase 'a' instead of 'A', for more meaningful actions
lib: update WinSparkle to 0.8.1
  • Loading branch information
fxliang authored and lotem committed Mar 29, 2024
1 parent d344d50 commit d918ace
Show file tree
Hide file tree
Showing 14 changed files with 349 additions and 203 deletions.
306 changes: 162 additions & 144 deletions RimeWithWeasel/RimeWithWeasel.cpp

Large diffs are not rendered by default.

19 changes: 17 additions & 2 deletions WeaselDeployer/SwitcherSettingsDialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,10 +104,25 @@ LRESULT SwitcherSettingsDialog::OnClose(UINT, WPARAM, LPARAM, BOOL&) {
return 0;
}

BOOL is_wow64() {
DWORD errorCode;
if (GetSystemWow64DirectoryW(NULL, 0) == 0)
if ((errorCode = GetLastError()) == ERROR_CALL_NOT_IMPLEMENTED)
return FALSE;
else
ExitProcess((UINT)errorCode);
else
return TRUE;
}

LRESULT SwitcherSettingsDialog::OnGetSchemata(WORD, WORD, HWND hWndCtl, BOOL&) {
HKEY hKey;
LSTATUS ret =
RegOpenKey(HKEY_LOCAL_MACHINE, _T("Software\\Rime\\Weasel"), &hKey);
std::wstring hPath;
if (is_wow64())
hPath = _T("Software\\WOW6432Node\\Rime\\Weasel");
else
hPath = _T("Software\\Rime\\Weasel");
LSTATUS ret = RegOpenKey(HKEY_LOCAL_MACHINE, hPath.c_str(), &hKey);
if (ret == ERROR_SUCCESS) {
WCHAR value[MAX_PATH];
DWORD len = sizeof(value);
Expand Down
81 changes: 81 additions & 0 deletions WeaselDeployer/WeaselDeployer.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,24 @@
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{F53F3E9C-CC4D-4D1D-9C2E-719FE60A7E6B}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>WeaselDeployer</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="..\weasel.props" />
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
Expand All @@ -23,28 +32,55 @@
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>$(PLATFORM_TOOLSET)</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>$(PLATFORM_TOOLSET)</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>$(PLATFORM_TOOLSET)</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>$(PLATFORM_TOOLSET)</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(SolutionDir)output\Win32\</OutDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(SolutionDir)output\</OutDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)output\Win32\</OutDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)output\</OutDir>
</PropertyGroup>
Expand All @@ -63,6 +99,24 @@
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>$(SolutionDir)\lib;$(BOOST_ROOT)\stage\lib;$(SolutionDir)\librime\build\lib\Debug;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>rime.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(SolutionDir)output\Win32\$(ProjectName)$(TargetExt)</OutputFile>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(SolutionDir)\include;$(BOOST_ROOT);$(SolutionDir)\librime\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<AdditionalOptions>/Zc:threadSafeInit- %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>$(SolutionDir)\lib64;$(BOOST_ROOT)\stage\lib;$(SolutionDir)\librime\build\lib\Debug;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>rime.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(SolutionDir)output\$(ProjectName)$(TargetExt)</OutputFile>
</Link>
</ItemDefinitionGroup>
Expand All @@ -85,6 +139,31 @@
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>rime.lib;rime.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(SolutionDir)\lib;$(BOOST_ROOT)\stage\lib;$(SolutionDir)\librime\build\lib\Release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<OutputFile>$(SolutionDir)output\Win32\$(ProjectName)$(TargetExt)</OutputFile>
</Link>
<Manifest>
<EnableDpiAwareness>PerMonitorHighDPIAware</EnableDpiAwareness>
</Manifest>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>Use</PrecompiledHeader>
<Optimization>Disabled</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(SolutionDir)\include;$(BOOST_ROOT);$(SolutionDir)\librime\include</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<AdditionalOptions>/Zc:threadSafeInit- %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>rime.lib;rime.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(SolutionDir)\lib64;$(BOOST_ROOT)\stage\lib;$(SolutionDir)\librime\build\lib\Release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<OutputFile>$(SolutionDir)output\$(ProjectName)$(TargetExt)</OutputFile>
</Link>
<Manifest>
Expand All @@ -108,7 +187,9 @@
<ClCompile Include="DictManagementDialog.cpp" />
<ClCompile Include="stdafx.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="SwitcherSettingsDialog.cpp" />
<ClCompile Include="UIStyleSettings.cpp" />
Expand Down
13 changes: 7 additions & 6 deletions WeaselServer/WeaselServer.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
<ProjectGuid>{A68C2A5C-D74D-4CB2-9E22-A4D2FC256A2D}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>WeaselServer</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="..\weasel.props" />
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
Expand Down Expand Up @@ -207,7 +208,7 @@
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(SolutionDir)output\</OutDir>
<OutDir>$(SolutionDir)output\Win32</OutDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
<LinkIncremental>true</LinkIncremental>
Expand All @@ -220,7 +221,7 @@
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<OutDir>$(SolutionDir)output\</OutDir>
<OutDir>$(SolutionDir)output\Win32\</OutDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<OutDir>$(SolutionDir)output\</OutDir>
Expand Down Expand Up @@ -285,7 +286,7 @@
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<TargetMachine>MachineX86</TargetMachine>
<OutputFile>$(SolutionDir)\output\$(ProjectName).exe</OutputFile>
<OutputFile>$(SolutionDir)\output\Win32\$(ProjectName).exe</OutputFile>
</Link>
<PostBuildEvent>
<Command>
Expand Down Expand Up @@ -365,7 +366,7 @@
</ResourceCompile>
<Link>
<AdditionalDependencies>imm32.lib;usp10.lib;rime.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(SolutionDir)\lib;$(BOOST_ROOT)\stage\lib;$(SolutionDir)\librime\build\lib\Debug;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalLibraryDirectories>$(SolutionDir)\lib64;$(BOOST_ROOT)\stage\lib;$(SolutionDir)\librime\build\lib\Debug;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<TargetMachine>MachineX64</TargetMachine>
Expand Down Expand Up @@ -438,7 +439,7 @@
</ResourceCompile>
<Link>
<AdditionalDependencies>imm32.lib;usp10.lib;rime.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(SolutionDir)\output\$(ProjectName).exe</OutputFile>
<OutputFile>$(SolutionDir)\output\Win32\$(ProjectName).exe</OutputFile>
<AdditionalLibraryDirectories>$(SolutionDir)\lib;$(BOOST_ROOT)\stage\lib;$(SolutionDir)\librime\build\lib\Release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<SubSystem>Windows</SubSystem>
<TargetMachine>MachineX86</TargetMachine>
Expand Down Expand Up @@ -533,7 +534,7 @@
<Link>
<AdditionalDependencies>imm32.lib;usp10.lib;rime.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(SolutionDir)\output\$(ProjectName).exe</OutputFile>
<AdditionalLibraryDirectories>$(SolutionDir)\lib;$(BOOST_ROOT)\stage\lib;$(SolutionDir)\librime\build\lib\Release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalLibraryDirectories>$(SolutionDir)\lib64;$(BOOST_ROOT)\stage\lib;$(SolutionDir)\librime\build\lib\Release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<GenerateDebugInformation>false</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<TargetMachine>MachineX64</TargetMachine>
Expand Down
13 changes: 7 additions & 6 deletions WeaselServer/WeaselServerApp.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,20 @@ namespace fs = boost::filesystem;
class WeaselServerApp {
public:
static bool execute(const fs::path& cmd, const std::wstring& args) {
return (int)ShellExecuteW(NULL, NULL, cmd.c_str(), args.c_str(), NULL,
SW_SHOWNORMAL) > 32;
return (uintptr_t)ShellExecuteW(NULL, NULL, cmd.c_str(), args.c_str(), NULL,
SW_SHOWNORMAL) > 32;
}

static bool explore(const fs::path& path) {
std::wstring quoted_path(L"\"" + path.wstring() + L"\"");
return (int)ShellExecuteW(NULL, L"open", L"explorer", quoted_path.c_str(),
NULL, SW_SHOWNORMAL) > 32;
return (uintptr_t)ShellExecuteW(NULL, L"open", L"explorer",
quoted_path.c_str(), NULL,
SW_SHOWNORMAL) > 32;
}

static bool open(const fs::path& path) {
return (int)ShellExecuteW(NULL, L"open", path.c_str(), NULL, NULL,
SW_SHOWNORMAL) > 32;
return (uintptr_t)ShellExecuteW(NULL, L"open", path.c_str(), NULL, NULL,
SW_SHOWNORMAL) > 32;
}

static bool check_update() {
Expand Down
65 changes: 40 additions & 25 deletions include/RimeWithWeasel.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,64 +21,78 @@ typedef std::map<std::string, bool> AppOptions;
typedef std::map<std::string, AppOptions, CaseInsensitiveCompare>
AppOptionsByAppName;
struct SessionStatus {
SessionStatus() : style(weasel::UIStyle()), __synced(false) {
SessionStatus() : style(weasel::UIStyle()), __synced(false), session_id(0) {
RIME_STRUCT(RimeStatus, status);
}
weasel::UIStyle style;
RimeStatus status;
bool __synced;
RimeSessionId session_id;
};
typedef std::map<UINT, SessionStatus> SessionStatusMap;
typedef std::map<DWORD, SessionStatus> SessionStatusMap;
typedef DWORD WeaselSessionId;
class RimeWithWeaselHandler : public weasel::RequestHandler {
public:
RimeWithWeaselHandler(weasel::UI* ui);
virtual ~RimeWithWeaselHandler();
virtual void Initialize();
virtual void Finalize();
virtual UINT FindSession(UINT session_id);
virtual UINT AddSession(LPWSTR buffer, EatLine eat = 0);
virtual UINT RemoveSession(UINT session_id);
virtual DWORD FindSession(WeaselSessionId ipc_id);
virtual DWORD AddSession(LPWSTR buffer, EatLine eat = 0);
virtual DWORD RemoveSession(WeaselSessionId ipc_id);
virtual BOOL ProcessKeyEvent(weasel::KeyEvent keyEvent,
UINT session_id,
WeaselSessionId ipc_id,
EatLine eat);
virtual void CommitComposition(UINT session_id);
virtual void ClearComposition(UINT session_id);
virtual void SelectCandidateOnCurrentPage(size_t index, UINT session_id);
virtual void CommitComposition(WeaselSessionId ipc_id);
virtual void ClearComposition(WeaselSessionId ipc_id);
virtual void SelectCandidateOnCurrentPage(size_t index,
WeaselSessionId ipc_id);
virtual bool HighlightCandidateOnCurrentPage(size_t index,
UINT session_id,
WeaselSessionId ipc_id,
EatLine eat);
virtual bool ChangePage(bool backward, UINT session_id, EatLine eat);
virtual void FocusIn(DWORD param, UINT session_id);
virtual void FocusOut(DWORD param, UINT session_id);
virtual void UpdateInputPosition(RECT const& rc, UINT session_id);
virtual bool ChangePage(bool backward, WeaselSessionId ipc_id, EatLine eat);
virtual void FocusIn(DWORD param, WeaselSessionId ipc_id);
virtual void FocusOut(DWORD param, WeaselSessionId ipc_id);
virtual void UpdateInputPosition(RECT const& rc, WeaselSessionId ipc_id);
virtual void StartMaintenance();
virtual void EndMaintenance();
virtual void SetOption(UINT session_id, const std::string& opt, bool val);
virtual void SetOption(WeaselSessionId ipc_id,
const std::string& opt,
bool val);
virtual void UpdateColorTheme(BOOL darkMode);

void OnUpdateUI(std::function<void()> const& cb);

private:
void _Setup();
bool _IsDeployerRunning();
void _UpdateUI(UINT session_id);
void _LoadSchemaSpecificSettings(UINT session_id,
void _UpdateUI(WeaselSessionId ipc_id);
void _LoadSchemaSpecificSettings(WeaselSessionId ipc_id,
const std::string& schema_id);
void _LoadAppInlinePreeditSet(UINT session_id, bool ignore_app_name = false);
void _LoadAppInlinePreeditSet(WeaselSessionId ipc_id,
bool ignore_app_name = false);
bool _ShowMessage(weasel::Context& ctx, weasel::Status& status);
bool _Respond(UINT session_id, EatLine eat);
void _ReadClientInfo(UINT session_id, LPWSTR buffer);
bool _Respond(WeaselSessionId ipc_id, EatLine eat);
void _ReadClientInfo(WeaselSessionId ipc_id, LPWSTR buffer);
void _GetCandidateInfo(weasel::CandidateInfo& cinfo, RimeContext& ctx);
void _GetStatus(weasel::Status& stat, UINT session_id, weasel::Context& ctx);
void _GetContext(weasel::Context& ctx, UINT session_id);
void _GetStatus(weasel::Status& stat,
WeaselSessionId ipc_id,
weasel::Context& ctx);
void _GetContext(weasel::Context& ctx, RimeSessionId session_id);
void _UpdateShowNotifications(RimeConfig* config, bool initialize = false);

bool _IsSessionTSF(UINT session_id);
void _UpdateInlinePreeditStatus(UINT session_id);
bool _IsSessionTSF(RimeSessionId session_id);
void _UpdateInlinePreeditStatus(WeaselSessionId ipc_id);
RimeSessionId _s(WeaselSessionId ipc_id) {
return (m_session_status_map[ipc_id].session_id);
}
SessionStatus& _session_status(WeaselSessionId ipc_id) {
return m_session_status_map[ipc_id];
}

AppOptionsByAppName m_app_options;
weasel::UI* m_ui; // reference
UINT m_active_session;
DWORD m_active_session;
bool m_disabled;
std::string m_last_schema_id;
std::string m_last_app_name;
Expand All @@ -99,4 +113,5 @@ class RimeWithWeaselHandler : public weasel::RequestHandler {
bool m_current_dark_mode;
bool m_global_ascii_mode;
int m_show_notifications_time;
DWORD m_pid;
};
Loading

0 comments on commit d918ace

Please sign in to comment.