Compare commits
99 commits
master-aut
...
master
Author | SHA1 | Date | |
---|---|---|---|
91e743572c | |||
80af06709f | |||
c28d3865bc | |||
c0299480ad | |||
e55207c46e | |||
036d17df97 | |||
1555bd7a12 | |||
a554bb1a92 | |||
3f54c42aaf | |||
7e57a373d8 | |||
edd0249b20 | |||
78cc398e30 | |||
f66604560b | |||
a7c58bc2a8 | |||
c00d3a1e15 | |||
5bca23615f | |||
d6173ba850 | |||
5784530204 | |||
cdabee7f20 | |||
901883399f | |||
8807bbfe80 | |||
186b4f46d4 | |||
e6b8ff34ed | |||
863cbfb53a | |||
c83e67354a | |||
2eb0052663 | |||
c438592ab0 | |||
cd5e5db816 | |||
8481890b52 | |||
a2fd5af13e | |||
dc628da723 | |||
203be3ce46 | |||
698ebb88c6 | |||
8f4d78910c | |||
0ca02a72f4 | |||
fc2d2dab8d | |||
33b8d1c4bc | |||
bec8a5b69f | |||
595902355e | |||
3219b5eeb9 | |||
77e23c41e1 | |||
0ce6a8619b | |||
ffacf70a4f | |||
02759c59f7 | |||
c1d2e3647b | |||
a74f2d0c82 | |||
b6bb5b3dda | |||
c5587fe3b3 | |||
ff713338e0 | |||
efe4e439d1 | |||
9d793b90e2 | |||
583a381c74 | |||
17c451652d | |||
a41e499bf0 | |||
fd0b3d65f8 | |||
e5302d1d9d | |||
d6a6bdc546 | |||
9afa4ddb72 | |||
4912be6cff | |||
66403012dc | |||
799ad11339 | |||
81253f28cc | |||
e4bd6c1ce4 | |||
c5704ea56b | |||
7976859639 | |||
f2096694c6 | |||
bee7dd0ef4 | |||
c0c9e1df14 | |||
a23ab3ac6e | |||
a9204e0892 | |||
9ae30a0607 | |||
3e352b5a94 | |||
47365dd7e0 | |||
8e2a459eae | |||
06496b9720 | |||
f3be74b328 | |||
01070d089d | |||
d3a2e52285 | |||
2a7063d992 | |||
209b657133 | |||
32ed1ce245 | |||
b18f49cda3 | |||
3a0d2d2ffe | |||
ce9d848388 | |||
aaa7c8ee75 | |||
2376226650 | |||
d66d037817 | |||
a337b0efcf | |||
4b5ed0b428 | |||
bcac03ef6a | |||
c9241e220c | |||
1612ee7472 | |||
78d8dabf39 | |||
39d1a29ced | |||
45b300d2a3 | |||
e2075ed9fc | |||
825cc5836c | |||
1532d181c4 | |||
fa357527fe |
26
.github/workflows/build-win64.yml
vendored
26
.github/workflows/build-win64.yml
vendored
|
@ -12,15 +12,31 @@ jobs:
|
||||||
install: git
|
install: git
|
||||||
- run: git config --global core.autocrlf input
|
- run: git config --global core.autocrlf input
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- name: Build Dino
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
- name: Install build-dependencies
|
||||||
run: |
|
run: |
|
||||||
msys2 -c './build-win64.sh --prepare'
|
msys2 -c './build-win64.sh --prepare'
|
||||||
msys2 -c './build-win64.sh'
|
- name: Build Dino+ (Meson, without saving)
|
||||||
- name: Build Dino Installer
|
run: |
|
||||||
|
msys2 -c './build-win64.sh -s meson -c -b -t -w'
|
||||||
|
- name: Build Dino+ (CMake)
|
||||||
|
run: |
|
||||||
|
msys2 -c './build-win64.sh -s cmake -c -b -t -i'
|
||||||
|
- name: Build Dino+ installer
|
||||||
run: |
|
run: |
|
||||||
msys2 -c './build-win64.sh --build-installer'
|
msys2 -c './build-win64.sh --build-installer'
|
||||||
- name: Upload Dino Installer
|
- name: Upload Dino+ installer
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: dino-installer
|
name: dino-plus-installer
|
||||||
path: windows-installer/dino-installer.exe
|
path: windows-installer/dino-installer.exe
|
||||||
|
- name: Release Dino+ installer
|
||||||
|
if: ${{ github.ref_type == 'tag' }}
|
||||||
|
uses: svenstaro/upload-release-action@2.9.0
|
||||||
|
with:
|
||||||
|
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
file: windows-installer/dino-installer.exe
|
||||||
|
asset_name: dino-plus-installer.exe
|
||||||
|
tag: ${{ github.ref }}
|
||||||
|
release_name: Dino+ ${{ github.ref_name }}
|
||||||
|
|
48
.github/workflows/build.yml
vendored
48
.github/workflows/build.yml
vendored
|
@ -7,34 +7,64 @@ jobs:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
- run: sudo rm /etc/apt/sources.list.d/microsoft-prod.list
|
||||||
- run: sudo apt-get update
|
- run: sudo apt-get update
|
||||||
- run: sudo apt-get remove libunwind-14-dev
|
- run: sudo apt-get remove libunwind-14-dev
|
||||||
- run: sudo apt-get install -y build-essential gettext cmake valac libgee-0.8-dev libsqlite3-dev libgtk-4-dev libnotify-dev libgpgme-dev libsoup2.4-dev libgcrypt20-dev libqrencode-dev libnice-dev libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libsrtp2-dev libwebrtc-audio-processing-dev libadwaita-1-dev libsignal-protocol-c-dev
|
- run: sudo apt-get install -y build-essential gettext cmake valac libgee-0.8-dev libsqlite3-dev libgtk-4-dev libnotify-dev libgpgme-dev libsoup2.4-dev libgcrypt20-dev libqrencode-dev libnice-dev libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libsrtp2-dev libadwaita-1-dev libsignal-protocol-c-dev libcanberra-dev
|
||||||
- run: ./configure --with-tests --with-libsignal-in-tree
|
- run: ./configure --release --no-debug --with-tests --enable-plugin=notification-sound --prefix=/usr --without-webrtc
|
||||||
- run: make
|
- run: cmake --build build
|
||||||
- run: build/xmpp-vala-test
|
- run: cmake --build build --target=test
|
||||||
- run: build/omemo-test
|
- name: Build DEB-package
|
||||||
|
run: cd build && cpack -G DEB
|
||||||
|
- name: Upload Dino+ DEB-package
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: dino-plus-deb
|
||||||
|
path: _packages/dino-plus.deb
|
||||||
|
- name: Release Dino+ DEB-package
|
||||||
|
if: ${{ github.ref_type == 'tag' }}
|
||||||
|
uses: svenstaro/upload-release-action@2.9.0
|
||||||
|
with:
|
||||||
|
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
file: _packages/dino-plus.deb
|
||||||
|
asset_name: dino-plus.deb
|
||||||
|
tag: ${{ github.ref }}
|
||||||
|
release_name: Dino+ ${{ github.ref_name }}
|
||||||
|
|
||||||
build-meson:
|
build-meson:
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
- run: sudo rm /etc/apt/sources.list.d/microsoft-prod.list
|
||||||
- run: sudo apt-get update
|
- run: sudo apt-get update
|
||||||
- run: sudo apt-get remove libunwind-14-dev
|
- run: sudo apt-get remove libunwind-14-dev
|
||||||
- run: sudo apt-get install -y build-essential gettext libadwaita-1-dev libcanberra-dev libgcrypt20-dev libgee-0.8-dev libgpgme-dev libgstreamer-plugins-base1.0-dev libgstreamer1.0-dev libgtk-4-dev libnice-dev libnotify-dev libqrencode-dev libsignal-protocol-c-dev libsoup-3.0-dev libsqlite3-dev libsrtp2-dev libwebrtc-audio-processing-dev meson valac
|
- run: sudo apt-get install -y build-essential gettext libadwaita-1-dev libcanberra-dev libgcrypt20-dev libgee-0.8-dev libgpgme-dev libgstreamer-plugins-base1.0-dev libgstreamer1.0-dev libgtk-4-dev libnice-dev libnotify-dev libqrencode-dev libsignal-protocol-c-dev libsoup2.4-dev libsqlite3-dev libsrtp2-dev meson valac
|
||||||
- run: meson setup build
|
- run: meson setup build -Duse-soup2=true -Dplugin-rtp-webrtc-audio-processing=disabled
|
||||||
- run: meson compile -C build
|
- run: meson compile -C build
|
||||||
|
- run: meson test -C build
|
||||||
build-flatpak:
|
build-flatpak:
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
container:
|
container:
|
||||||
image: bilelmoussaoui/flatpak-github-actions:gnome-44
|
image: bilelmoussaoui/flatpak-github-actions:gnome-44
|
||||||
options: --privileged
|
options: --privileged
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
submodules: true
|
||||||
|
- run: flatpak repair --user
|
||||||
- uses: flatpak/flatpak-github-actions/flatpak-builder@v6.1
|
- uses: flatpak/flatpak-github-actions/flatpak-builder@v6.1
|
||||||
with:
|
with:
|
||||||
manifest-path: im.dino.Dino.json
|
manifest-path: im.dino.Dino.json
|
||||||
build-bundle: false
|
build-bundle: true
|
||||||
|
- name: Release Dino+ flatpak
|
||||||
|
if: ${{ github.ref_type == 'tag' }}
|
||||||
|
uses: svenstaro/upload-release-action@2.9.0
|
||||||
|
with:
|
||||||
|
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
file: app.flatpak
|
||||||
|
asset_name: app.flatpak
|
||||||
|
tag: ${{ github.ref }}
|
||||||
|
release_name: Dino+ ${{ github.ref_name }}
|
||||||
|
|
6
.gitignore
vendored
6
.gitignore
vendored
|
@ -6,6 +6,10 @@ Makefile
|
||||||
.idea
|
.idea
|
||||||
.sqlite3
|
.sqlite3
|
||||||
gschemas.compiled
|
gschemas.compiled
|
||||||
windows-installer/win64-dist/
|
windows-installer/win64-*/
|
||||||
*.exe
|
*.exe
|
||||||
*.dll
|
*.dll
|
||||||
|
*.flatpak
|
||||||
|
flatpak-dist
|
||||||
|
.flatpak-builder
|
||||||
|
*.zst
|
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
[submodule "shared-modules"]
|
||||||
|
path = shared-modules
|
||||||
|
url = https://github.com/flathub/shared-modules.git
|
54
BUILD_MACOS.md
Normal file
54
BUILD_MACOS.md
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
Here are the instructions to anyone whom wants to try the build themselves.
|
||||||
|
It is assumed that you have `brew` installed, know your way around terminal, and generally understand what you're doing.
|
||||||
|
|
||||||
|
## Build
|
||||||
|
|
||||||
|
1. Start with an already existing build instructions of the original project:
|
||||||
|
|
||||||
|
`https://github.com/dino/dino/wiki/macOS`
|
||||||
|
|
||||||
|
2. On step 4, replace the path to the upstream repo with this one:
|
||||||
|
|
||||||
|
```
|
||||||
|
git clone https://github.com/mxlgv/dino
|
||||||
|
cd dino
|
||||||
|
```
|
||||||
|
|
||||||
|
3. On step 5 run `./configure --with-libsoup3`.
|
||||||
|
|
||||||
|
4. Continue the build according to the original instructions.
|
||||||
|
|
||||||
|
## Install with Brew
|
||||||
|
|
||||||
|
To build Dino using this formula, follow these instructions:
|
||||||
|
|
||||||
|
```
|
||||||
|
brew tap mxlgv/homebrew-dino
|
||||||
|
brew install mxlgv/homebrew-dino/dino
|
||||||
|
```
|
||||||
|
|
||||||
|
You can start the Dino client installed via homebrew with the following command:
|
||||||
|
|
||||||
|
```
|
||||||
|
./opt/homebrew/Cellar/dino/3/bin/dino
|
||||||
|
```
|
||||||
|
|
||||||
|
You can create a shortcut with a symbolic link pointing to this file, so that you can open it in a more convenient way.
|
||||||
|
|
||||||
|
If you encounter an error related to rpath, you need to add `DYLD_LIBRARY_PATH` to the environment variable:
|
||||||
|
|
||||||
|
```
|
||||||
|
export DYLD_LIBRARY_PATH=/opt/homebrew/Cellar/dino/3/lib
|
||||||
|
```
|
||||||
|
|
||||||
|
## Notifications
|
||||||
|
|
||||||
|
There is a draft PR which can be used to enable notifications: https://github.com/mxlgv/dino/pull/45
|
||||||
|
|
||||||
|
## Start Dino
|
||||||
|
|
||||||
|
In order to run Dino, just run in the build folder:
|
||||||
|
|
||||||
|
```
|
||||||
|
./dino
|
||||||
|
```
|
|
@ -10,11 +10,24 @@ else ()
|
||||||
set(PROJECT_VERSION ${VERSION_FULL})
|
set(PROJECT_VERSION ${VERSION_FULL})
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
|
include(CTest)
|
||||||
|
|
||||||
|
option(PLUGIN_RTP_WEBRTC_AUDIO_PROCESSING "Use WebRTC audio processing" ON)
|
||||||
|
option(WITH_WASAPI "Use wasapi instead of directsound on windows" ON)
|
||||||
|
|
||||||
|
# https://gitlab.kitware.com/cmake/cmake/-/issues/19804
|
||||||
|
if (WIN32)
|
||||||
|
list(APPEND CMAKE_FIND_LIBRARY_SUFFIXES .dll)
|
||||||
|
endif()
|
||||||
|
|
||||||
# Prepare Plugins
|
# Prepare Plugins
|
||||||
set(DEFAULT_PLUGINS omemo;openpgp;http-files;ice;rtp)
|
set(DEFAULT_PLUGINS omemo;openpgp;http-files;ice;rtp)
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
set(DEFAULT_PLUGINS ${DEFAULT_PLUGINS};win32-fonts;windows-notification)
|
list(APPEND DEFAULT_PLUGINS win32-fonts windows-notification)
|
||||||
endif (WIN32)
|
else()
|
||||||
|
list(APPEND DEFAULT_PLUGINS phone-ringer)
|
||||||
|
endif()
|
||||||
|
|
||||||
foreach (plugin ${DEFAULT_PLUGINS})
|
foreach (plugin ${DEFAULT_PLUGINS})
|
||||||
if ("$CACHE{DINO_PLUGIN_ENABLED_${plugin}}" STREQUAL "")
|
if ("$CACHE{DINO_PLUGIN_ENABLED_${plugin}}" STREQUAL "")
|
||||||
if (NOT DEFINED DINO_PLUGIN_ENABLED_${plugin}})
|
if (NOT DEFINED DINO_PLUGIN_ENABLED_${plugin}})
|
||||||
|
@ -68,6 +81,8 @@ macro(set_path what val desc)
|
||||||
endif()
|
endif()
|
||||||
endmacro(set_path)
|
endmacro(set_path)
|
||||||
|
|
||||||
|
set(LOCALEDIR_NAME "share/locale")
|
||||||
|
|
||||||
string(REGEX REPLACE "^liblib" "lib" LIBDIR_NAME "lib${LIB_SUFFIX}")
|
string(REGEX REPLACE "^liblib" "lib" LIBDIR_NAME "lib${LIB_SUFFIX}")
|
||||||
set_path(CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}" "Installation directory for architecture-independent files")
|
set_path(CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}" "Installation directory for architecture-independent files")
|
||||||
set_path(EXEC_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}" "Installation directory for architecture-dependent files")
|
set_path(EXEC_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}" "Installation directory for architecture-dependent files")
|
||||||
|
@ -81,7 +96,7 @@ set_path(SERVICE_FILE_INSTALL_DIR "${SHARE_INSTALL_PREFIX}/dbus-1/services" "Ins
|
||||||
set_path(ICON_INSTALL_DIR "${SHARE_INSTALL_PREFIX}/icons" "Installation directory for icons")
|
set_path(ICON_INSTALL_DIR "${SHARE_INSTALL_PREFIX}/icons" "Installation directory for icons")
|
||||||
set_path(INCLUDE_INSTALL_DIR "${EXEC_INSTALL_PREFIX}/include" "Installation directory for C header files")
|
set_path(INCLUDE_INSTALL_DIR "${EXEC_INSTALL_PREFIX}/include" "Installation directory for C header files")
|
||||||
set_path(LIB_INSTALL_DIR "${EXEC_INSTALL_PREFIX}/${LIBDIR_NAME}" "Installation directory for object code libraries")
|
set_path(LIB_INSTALL_DIR "${EXEC_INSTALL_PREFIX}/${LIBDIR_NAME}" "Installation directory for object code libraries")
|
||||||
set_path(LOCALE_INSTALL_DIR "${SHARE_INSTALL_PREFIX}/locale" "Installation directory for locale files")
|
set_path(LOCALE_INSTALL_DIR "${EXEC_INSTALL_PREFIX}/${LOCALEDIR_NAME}" "Installation directory for locale files")
|
||||||
set_path(PLUGIN_INSTALL_DIR "${LIB_INSTALL_DIR}/dino/plugins" "Installation directory for dino plugin object code files")
|
set_path(PLUGIN_INSTALL_DIR "${LIB_INSTALL_DIR}/dino/plugins" "Installation directory for dino plugin object code files")
|
||||||
set_path(VAPI_INSTALL_DIR "${SHARE_INSTALL_PREFIX}/vala/vapi" "Installation directory for Vala API files")
|
set_path(VAPI_INSTALL_DIR "${SHARE_INSTALL_PREFIX}/vala/vapi" "Installation directory for Vala API files")
|
||||||
|
|
||||||
|
@ -218,6 +233,9 @@ add_subdirectory(main)
|
||||||
add_subdirectory(crypto-vala)
|
add_subdirectory(crypto-vala)
|
||||||
add_subdirectory(plugins)
|
add_subdirectory(plugins)
|
||||||
|
|
||||||
|
# To generate a DEB package
|
||||||
|
include(Packing)
|
||||||
|
|
||||||
# uninstall target
|
# uninstall target
|
||||||
configure_file("${CMAKE_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in" "${CMAKE_BINARY_DIR}/cmake_uninstall.cmake" IMMEDIATE @ONLY)
|
configure_file("${CMAKE_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in" "${CMAKE_BINARY_DIR}/cmake_uninstall.cmake" IMMEDIATE @ONLY)
|
||||||
add_custom_target(uninstall COMMAND ${CMAKE_COMMAND} -P ${CMAKE_BINARY_DIR}/cmake_uninstall.cmake COMMENT "Uninstall the project...")
|
add_custom_target(uninstall COMMAND ${CMAKE_COMMAND} -P ${CMAKE_BINARY_DIR}/cmake_uninstall.cmake COMMENT "Uninstall the project...")
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
Dino - Modern Jabber/XMPP Client using GTK+/Vala
|
Dino+, a modern XMPP/Jabber client software based on Dino
|
||||||
Copyright (C) 2016-2020 Dino contributors
|
Copyright (C) 2016-2023 Dino contributors
|
||||||
|
Copyright (C) 2024 Dino+ contributors
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
|
@ -1,56 +0,0 @@
|
||||||
![Dino (WIN64)](https://dino.im/img/readme_header.svg)
|
|
||||||
=======
|
|
||||||
|
|
||||||
![screenshots](https://dino.im/img/screenshot-main.png)
|
|
||||||
|
|
||||||
Build on Windows (x86_64)
|
|
||||||
------------
|
|
||||||
- Install and configure the [MSYS2](https://www.msys2.org/) package;
|
|
||||||
- Go to `MINGW64` environment;
|
|
||||||
- Clone project:
|
|
||||||
```sh
|
|
||||||
git clone https://github.com/mxlgv/dino && cd dino
|
|
||||||
```
|
|
||||||
- Run the script to install dependencies:
|
|
||||||
```sh
|
|
||||||
./build-win64.sh --prepare
|
|
||||||
```
|
|
||||||
- Start the build (the builded distribution is available in the `windows-installer/dist-win64` folder):
|
|
||||||
```sh
|
|
||||||
./build-win64.sh
|
|
||||||
```
|
|
||||||
Note: the build script has some other options, their description can be found using the `--help`.
|
|
||||||
|
|
||||||
Build Windows Installer (NSIS)
|
|
||||||
------------
|
|
||||||
Before this, you must build the project according to the instructions above. It's worth making sure that `windows-installer/dist-win64` is not empty.
|
|
||||||
Now you should run:
|
|
||||||
```sh
|
|
||||||
./build-win64.sh --build-installer
|
|
||||||
```
|
|
||||||
|
|
||||||
The builded installer will be available in the directory `windows-installer/dino-installer.exe`.
|
|
||||||
|
|
||||||
Resources
|
|
||||||
---------
|
|
||||||
- Check out the [Dino website](https://dino.im).
|
|
||||||
- Join our XMPP channel at `chat@dino.im`.
|
|
||||||
- The [wiki](https://github.com/dino/dino/wiki) provides additional information.
|
|
||||||
|
|
||||||
License
|
|
||||||
-------
|
|
||||||
Dino - Modern Jabber/XMPP Client using GTK+/Vala
|
|
||||||
Copyright (C) 2016-2023 Dino contributors
|
|
||||||
|
|
||||||
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/>.
|
|
150
README.md
150
README.md
|
@ -1,37 +1,163 @@
|
||||||
![Dino](https://dino.im/img/readme_header.svg)
|
This is Dino+<br />
|
||||||
|
A modern XMPP/Jabber client software, based on [Dino](https://github.com/dino/dino/)
|
||||||
=======
|
=======
|
||||||
|
|
||||||
![screenshots](https://dino.im/img/screenshot-main.png)
|
![screenshots](dino_plus.png)
|
||||||
|
|
||||||
Installation
|
Project description
|
||||||
------------
|
------------
|
||||||
Have a look at the [prebuilt packages](https://github.com/dino/dino/wiki/Distribution-Packages).
|
Dino+ is a fork of [Dino](https://github.com/dino/dino), a modern XMPP/Jabber client written in Vala using GTK+, which includes a few relatively minor but important quality-of-life features.
|
||||||
|
|
||||||
Build
|
It was created due to upstream project's maintainers being seemingly unwilling to accept PRs from the community. As of March 2024, there are over 50 PRs pending, most of which are silently ignored.
|
||||||
|
|
||||||
|
Some of the features that Dino+ implements:
|
||||||
|
|
||||||
|
* Windows support
|
||||||
|
* Proper sync for chats history, including "scroll-to-load"
|
||||||
|
* Forced MAM sync for chats
|
||||||
|
* Password change via GUI
|
||||||
|
* Optional support for Meson build system
|
||||||
|
* Some additional QoL-features
|
||||||
|
|
||||||
|
What's currently in the works:
|
||||||
|
|
||||||
|
* Multiple UI fixes
|
||||||
|
* Fixes for sound notifications
|
||||||
|
* MacOS support for Mac silicon
|
||||||
|
* and more
|
||||||
|
|
||||||
|
Dino+ is currently to be considered an alpha-quality product. Please open an issue or send a PR if you spot or fix any bugs.
|
||||||
|
|
||||||
|
OS support
|
||||||
|
------------
|
||||||
|
* Linux (flatpaks are targeted for Ubuntu 22.04+)
|
||||||
|
* Windows 10\11
|
||||||
|
* MacOS via [brew](https://brew.sh/) (very experimental, see below)
|
||||||
|
|
||||||
|
Officially, we support only x86_64 architecture. Whilst you may be able to compile this code for ARM-based platforms (like Pinephone or MacOS), there's zero guarantees that it'll compile or function properly, as we don't have the hardware and the time to test it out.
|
||||||
|
|
||||||
|
Installation (prebuilt packages & AUR)
|
||||||
|
------------
|
||||||
|
Have a look at our [releases](https://github.com/mxlgv/dino/releases).
|
||||||
|
|
||||||
|
Windows installer is self-explanatory, and will place a shortcut on your desktop. Ignore the possible warning from Windows Defender: it's caused by the fact that installer does not have a digital signature.
|
||||||
|
|
||||||
|
Deb package is built and tested only for Ubuntu 22.04, but it may work on its derivatives as well, such as Pop!_OS or Linux Mint.
|
||||||
|
|
||||||
|
Flatpak is not present in Flathub yet, but you can install it manually. The commands below assume that you have "flatpak" package of your distro installed in your system. If it is not, please refer to https://flatpak.org/setup/
|
||||||
|
|
||||||
|
1) Download the .flatpak file from [releases](https://github.com/mxlgv/dino/releases)
|
||||||
|
2) Add default Flatpak repo:
|
||||||
|
```
|
||||||
|
flatpak remote-add --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo
|
||||||
|
```
|
||||||
|
3) Change the directory to the one you've downloaded the .flatpak to and run (you may have to change the file name in this command):
|
||||||
|
```
|
||||||
|
flatpak install ./im.dino.Dino.flatpak
|
||||||
|
```
|
||||||
|
4) To launch the program, run either
|
||||||
|
```
|
||||||
|
/usr/bin/dino
|
||||||
|
```
|
||||||
|
or
|
||||||
|
```
|
||||||
|
flatpak run im.dino.Dino
|
||||||
|
```
|
||||||
|
|
||||||
|
Flatpak distribution is confirmed to be working on Arch Testing, Manjaro Stable, Void Linux and Linux Mint.
|
||||||
|
|
||||||
|
Arch Linux & Manjaro users may install `dino-plus-git` package from [AUR](https://aur.archlinux.org/packages/dino-plus-git) via any helper of their choice.
|
||||||
|
|
||||||
|
Build on Linux
|
||||||
-----
|
-----
|
||||||
Make sure to install all [dependencies](https://github.com/dino/dino/wiki/Build#dependencies).
|
Make sure to install all [dependencies](https://github.com/dino/dino/wiki/Build#dependencies).
|
||||||
|
|
||||||
./configure
|
./configure --release --no-debug --with-tests --enable-plugin=notification-sound --prefix=/usr
|
||||||
make
|
make
|
||||||
build/dino
|
build/dino
|
||||||
|
|
||||||
|
Additionally, you might need to install `gst-plugins-bad` and `webrtc-audio-processing` packages (or however they might be called in your distro), if you want to have noise cancelling and gain control. If you don't want that or your distro don't have that package, add "--without-webrtc" (without quotes) to the first command.
|
||||||
|
|
||||||
|
If you want to use `meson` build system, follow the next instructions:
|
||||||
|
|
||||||
|
meson setup build
|
||||||
|
meson configure --prefix $PWD/build/install --libdir lib build
|
||||||
|
meson compile -C build
|
||||||
|
meson install -C build
|
||||||
|
LD_LIBRARY_PATH+=:$PWD/build/install/lib build/install/bin/dino
|
||||||
|
|
||||||
|
If your `nice` library depends on `libsoup-2.4` (consider `ldd` output for the `libnice.so`), you should additionally specify `-Duse-soup2=true` option.
|
||||||
|
`LD_LIBRARY_PATH` should point to the directory containing the `libdino.so` library.
|
||||||
|
Skip `meson configure` step, if you want to install the program globally.
|
||||||
|
You can specify any convenient directory in the option `--prefix` where the program will be installed.
|
||||||
|
|
||||||
|
If there is no `webrtcdsp` plugin in your system (check this by calling `gst-inspect-1.0 webrtcdsp`) you should pass extra argument:
|
||||||
|
|
||||||
|
* `--without-webrtcdsp` for `./configure`;
|
||||||
|
* `-Dplugin-rtp-webrtc-audio-processing=disabled` for `meson`;
|
||||||
|
* `-DPLUGIN_RTP_WEBRTC_AUDIO_PROCESSING=OFF` for `cmake`.
|
||||||
|
|
||||||
|
Build on Windows (x86_64)
|
||||||
|
------------
|
||||||
|
- Install and configure the [MSYS2](https://www.msys2.org/) package;
|
||||||
|
- Go to `MINGW64` environment;
|
||||||
|
- Clone project:
|
||||||
|
```sh
|
||||||
|
git clone https://github.com/mxlgv/dino && cd dino
|
||||||
|
```
|
||||||
|
- Run the script to install dependencies:
|
||||||
|
```sh
|
||||||
|
./build-win64.sh --prepare
|
||||||
|
```
|
||||||
|
- Start the build (the builded distribution is available in the `windows-installer/dist-win64` folder):
|
||||||
|
```sh
|
||||||
|
./build-win64.sh
|
||||||
|
```
|
||||||
|
If you want to use meson build system, please use `-s meson` key as the first argument, i.e.
|
||||||
|
```sh
|
||||||
|
bash build-win64.sh -s meson -c -b
|
||||||
|
```
|
||||||
|
will do the same as commands above, but using meson.
|
||||||
|
|
||||||
|
Note: the build script has some other options, their description can be found using the `--help`.
|
||||||
|
|
||||||
|
Build Windows Installer (NSIS)
|
||||||
|
------------
|
||||||
|
Before this, you must build the project according to the instructions above. It's worth making sure that `windows-installer/dist-win64` is not empty.
|
||||||
|
Now you should run:
|
||||||
|
```sh
|
||||||
|
./build-win64.sh --build-installer
|
||||||
|
```
|
||||||
|
|
||||||
|
Build on MacOS
|
||||||
|
------------
|
||||||
|
Builds for Mac are currently available only as a [brew](https://brew.sh/) formulae. Please follow [these instructions](https://github.com/mxlgv/dino/blob/master/BUILD_MACOS.md) to produce a build.
|
||||||
|
|
||||||
|
Please note that Mac support is very experimental, and currently missing support for event notifications, among other things. You have been warned.
|
||||||
|
|
||||||
Resources
|
Resources
|
||||||
---------
|
---------
|
||||||
- Check out the [Dino website](https://dino.im).
|
- Original project's [website](https://dino.im).
|
||||||
- Join our XMPP channel at `chat@dino.im`.
|
- Dino's chat room `chat@dino.im` (please don't post there any issues related to this fork!)
|
||||||
- The [wiki](https://github.com/dino/dino/wiki) provides additional information.
|
- The upstream project's [wiki](https://github.com/dino/dino/wiki) provides additional information.
|
||||||
|
|
||||||
Contribute
|
Contribute
|
||||||
----------
|
----------
|
||||||
- Pull requests are welcome. [These](https://github.com/dino/dino/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22) might be good first issues. Please discuss bigger changes in our channel first.
|
- Pull requests are welcome!
|
||||||
- Look at [how to debug](https://github.com/dino/dino/wiki/Debugging) Dino before you report a bug.
|
- Look at [how to debug](https://github.com/dino/dino/wiki/Debugging) Dino before you report a bug.
|
||||||
- Help [translating](https://github.com/dino/dino/wiki/Translations) Dino into your language.
|
- Help [translating](https://github.com/dino/dino/wiki/Translations) Dino into your language.
|
||||||
- Make a [donation](https://dino.im/#donate).
|
|
||||||
|
Special thanks
|
||||||
|
----------
|
||||||
|
We'd like to thank all of the contributors whom provided the PRs used in this project.
|
||||||
|
|
||||||
|
We also recognise the previous efforts of [LAGonauta](https://github.com/LAGonauta) without whom Windows build wouldn't be available.
|
||||||
|
|
||||||
License
|
License
|
||||||
-------
|
-------
|
||||||
Dino - Modern Jabber/XMPP Client using GTK+/Vala
|
Dino+, a modern XMPP/Jabber client software based on Dino
|
||||||
Copyright (C) 2016-2023 Dino contributors
|
Copyright (C) 2016-2023 Dino contributors
|
||||||
|
Copyright (C) 2024 Dino+ contributors
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|
90
build-flatpack.sh
Executable file
90
build-flatpack.sh
Executable file
|
@ -0,0 +1,90 @@
|
||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
APP_NAME="im.dino.Dino"
|
||||||
|
DIST_NAME=${DIST_NAME:-"${APP_NAME}.flatpak"}
|
||||||
|
DIST_DIR="$PWD/flatpak-dist"
|
||||||
|
BUILD_TEMP_DIR="$DIST_DIR/buildtemp"
|
||||||
|
BUILD_EXPORT_DIR="$DIST_DIR/export"
|
||||||
|
|
||||||
|
msg()
|
||||||
|
{
|
||||||
|
echo -e "\e[32m$1\e[0m"
|
||||||
|
}
|
||||||
|
|
||||||
|
fatal()
|
||||||
|
{
|
||||||
|
echo -e "\e[31m$1\e[0m"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
get_flatpak_dependencies()
|
||||||
|
{
|
||||||
|
msg "Installing Flatpak dependencies..."
|
||||||
|
flatpak remote-add --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo
|
||||||
|
flatpak install flathub org.gnome.Sdk//44
|
||||||
|
flatpak install flathub org.gnome.Platform//44
|
||||||
|
msg "Flatpak dependencies installed"
|
||||||
|
}
|
||||||
|
|
||||||
|
pull_shared_modules()
|
||||||
|
{
|
||||||
|
msg "Pulling shared modules..."
|
||||||
|
git submodule init
|
||||||
|
git submodule update
|
||||||
|
msg "Shared modules successfully pulled"
|
||||||
|
}
|
||||||
|
|
||||||
|
prepare()
|
||||||
|
{
|
||||||
|
get_flatpak_dependencies
|
||||||
|
pull_shared_modules
|
||||||
|
}
|
||||||
|
|
||||||
|
build()
|
||||||
|
{
|
||||||
|
msg "Build commencing!"
|
||||||
|
rm -rf $BUILD_TEMP_DIR
|
||||||
|
flatpak-builder --install-deps-from=flathub $BUILD_TEMP_DIR "${APP_NAME}.json"
|
||||||
|
flatpak build-export $BUILD_EXPORT_DIR $BUILD_TEMP_DIR
|
||||||
|
flatpak build-bundle $BUILD_EXPORT_DIR $DIST_NAME $APP_NAME
|
||||||
|
msg "Flatpack bundle ready and saved to ${DIST_NAME}"
|
||||||
|
}
|
||||||
|
|
||||||
|
clean()
|
||||||
|
{
|
||||||
|
msg "Wiping intermediate files..."
|
||||||
|
rm -rf $BUILD_TEMP_DIR $BUILD_EXPORT_DIR
|
||||||
|
msg "Cleanup complete!"
|
||||||
|
}
|
||||||
|
|
||||||
|
help()
|
||||||
|
{
|
||||||
|
cat << EOF
|
||||||
|
usage: $0 [OPTION]
|
||||||
|
--prepare install build dependencies
|
||||||
|
--build build the project
|
||||||
|
--clean remove build artifacts
|
||||||
|
--help show this help
|
||||||
|
|
||||||
|
Bundle is saved to ${APP_NAME}.flatpak by default.
|
||||||
|
Set DIST_NAME variable to customize output file name:
|
||||||
|
'DIST_NAME=customname.flatpak $0'
|
||||||
|
|
||||||
|
Running without parameters is equivalent to running:
|
||||||
|
'--prepare', '--build' and '--clean'
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
case $1 in
|
||||||
|
"--prepare" ) prepare ;;
|
||||||
|
"--build" ) build ;;
|
||||||
|
"--help" ) help ;;
|
||||||
|
"--clean" ) clean;;
|
||||||
|
"" )
|
||||||
|
prepare
|
||||||
|
build
|
||||||
|
clean
|
||||||
|
;;
|
||||||
|
*) fatal "Unknown argument!"
|
||||||
|
esac
|
263
build-win64.sh
263
build-win64.sh
|
@ -1,8 +1,12 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
set -e
|
|
||||||
|
|
||||||
DIST_DIR="$PWD/windows-installer/win64-dist"
|
set -eu
|
||||||
|
|
||||||
|
PROJ_DIR=$PWD
|
||||||
|
DIST_DIR=${PROJ_DIR}/windows-installer/win64-dist
|
||||||
|
BUILD_DIR=$PROJ_DIR/build
|
||||||
JOBS=$NUMBER_OF_PROCESSORS
|
JOBS=$NUMBER_OF_PROCESSORS
|
||||||
|
build_sys='cmake'
|
||||||
|
|
||||||
msg()
|
msg()
|
||||||
{
|
{
|
||||||
|
@ -17,17 +21,31 @@ fatal()
|
||||||
|
|
||||||
download_yolort()
|
download_yolort()
|
||||||
{
|
{
|
||||||
file_name=cppwinrt-2.0.210122.3+windows-10.0.19041+yolort-835cd4e.zip
|
file_name=yolort.zip
|
||||||
yolort_dir="$PWD/plugins/windows-notification/yolort"
|
yolort_dir="$PROJ_DIR/plugins/windows-notification/yolort"
|
||||||
|
|
||||||
rm -rf "$yolort_dir"
|
rm -rf "$yolort_dir"
|
||||||
mkdir "$yolort_dir"
|
mkdir "$yolort_dir"
|
||||||
curl -L -o "$file_name" "https://github.com/LAGonauta/YoloRT/releases/download/v1.0.0/$file_name"
|
curl -L -o "$file_name" "https://github.com/mxlgv/YoloRT/releases/download/dev1/$file_name"
|
||||||
echo "675a6d943c97b4acdbfaa473f68d3241d1798b31a67b5529c8d29fc0176a1707 $file_name" | sha256sum --check --status
|
echo "c2727e390da7e842f66e0a4cf0a9f5d9dfb665115bb554152d98f108d322bbc1 $file_name" | sha256sum --check --status
|
||||||
unzip -o "$file_name" -d "$yolort_dir"
|
unzip -o "$file_name" -d "$yolort_dir"
|
||||||
rm -f "$file_name"
|
rm -f "$file_name"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
download_gtk4_git()
|
||||||
|
{
|
||||||
|
# FIXME: The bug fix https://gitlab.gnome.org/GNOME/gtk/-/issues/3749 is currently only available in the main branch,
|
||||||
|
# so GTK4 was builded from it. Needs to be replaced with a package from the MSYS2 repository when the changes get there.
|
||||||
|
url="https://github.com/mxlgv/mingw-w64-gtk4-git/releases/download/rel1"
|
||||||
|
gtk_pkg="mingw-w64-x86_64-gtk4-git-4.14.1.r62.gb1eed1c153-1-any.pkg.tar.zst"
|
||||||
|
gtk_gstreamer_pkg="mingw-w64-x86_64-gtk4-media-gstreamer-git-4.14.1.r62.gb1eed1c153-1-any.pkg.tar.zst"
|
||||||
|
|
||||||
|
curl -L -o "$gtk_pkg" "$url/$gtk_pkg"
|
||||||
|
curl -L -o "$gtk_gstreamer_pkg" "$url/$gtk_gstreamer_pkg"
|
||||||
|
|
||||||
|
pacman -U --needed --noconfirm "$gtk_pkg" "$gtk_gstreamer_pkg"
|
||||||
|
}
|
||||||
|
|
||||||
prepare()
|
prepare()
|
||||||
{
|
{
|
||||||
msg "Installing MINGW64 build dependencies"
|
msg "Installing MINGW64 build dependencies"
|
||||||
|
@ -36,7 +54,6 @@ prepare()
|
||||||
mingw64/mingw-w64-x86_64-gcc \
|
mingw64/mingw-w64-x86_64-gcc \
|
||||||
mingw64/mingw-w64-x86_64-cmake \
|
mingw64/mingw-w64-x86_64-cmake \
|
||||||
mingw64/mingw-w64-x86_64-ninja \
|
mingw64/mingw-w64-x86_64-ninja \
|
||||||
mingw64/mingw-w64-x86_64-gtk4 \
|
|
||||||
mingw64/mingw-w64-x86_64-libadwaita \
|
mingw64/mingw-w64-x86_64-libadwaita \
|
||||||
mingw64/mingw-w64-x86_64-sqlite3 \
|
mingw64/mingw-w64-x86_64-sqlite3 \
|
||||||
mingw64/mingw-w64-x86_64-openssl \
|
mingw64/mingw-w64-x86_64-openssl \
|
||||||
|
@ -57,12 +74,15 @@ prepare()
|
||||||
mingw64/mingw-w64-x86_64-nsis \
|
mingw64/mingw-w64-x86_64-nsis \
|
||||||
mingw64/mingw-w64-x86_64-libsignal-protocol-c \
|
mingw64/mingw-w64-x86_64-libsignal-protocol-c \
|
||||||
mingw64/mingw-w64-x86_64-icu \
|
mingw64/mingw-w64-x86_64-icu \
|
||||||
mingw64/mingw-w64-x86_64-webrtc-audio-processing \
|
mingw64/mingw-w64-x86_64-meson \
|
||||||
git \
|
git \
|
||||||
make \
|
make \
|
||||||
unzip \
|
unzip \
|
||||||
curl
|
curl
|
||||||
|
|
||||||
|
msg "Downloading and install git versions of gtk4 and gtk4-media-gstreamer packages"
|
||||||
|
download_gtk4_git
|
||||||
|
|
||||||
msg "Successfully installed!"
|
msg "Successfully installed!"
|
||||||
|
|
||||||
msg "Download YoloRT headers"
|
msg "Download YoloRT headers"
|
||||||
|
@ -71,60 +91,100 @@ prepare()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
configure()
|
configure_cmake()
|
||||||
{
|
{
|
||||||
msg "Running configuration for Windows"
|
msg "Running configuration for Windows"
|
||||||
./configure --program-prefix="$DIST_DIR" --no-debug --release --disable-fast-vapi --with-libsoup3
|
./configure --program-prefix="$DIST_DIR" --no-debug --release --disable-fast-vapi --with-libsoup3 --with-tests
|
||||||
msg "Configured!"
|
msg "Configured!"
|
||||||
}
|
}
|
||||||
|
|
||||||
build()
|
build_cmake()
|
||||||
{
|
{
|
||||||
msg "Started building on $JOBS threads"
|
msg "Started building on $JOBS threads"
|
||||||
make -j"$JOBS"
|
make -j"$JOBS"
|
||||||
msg "Successfully builded!"
|
msg "Successfully builded!"
|
||||||
|
msg "Installing Dino .."
|
||||||
|
make install
|
||||||
|
}
|
||||||
|
|
||||||
|
test_cmake()
|
||||||
|
{
|
||||||
|
msg "Run tests"
|
||||||
|
make test
|
||||||
|
}
|
||||||
|
|
||||||
|
configure_meson()
|
||||||
|
{
|
||||||
|
arg=${1:-"none"}
|
||||||
|
encr=${2:-"auto"}
|
||||||
|
local cmd=""
|
||||||
|
if [ x"${arg}" == x"reconfig" ]; then
|
||||||
|
cmd=--reconfigure
|
||||||
|
fi
|
||||||
|
mkdir -p $BUILD_DIR
|
||||||
|
meson setup ${cmd} --prefix "$DIST_DIR" \
|
||||||
|
-D crypto-backend=${encr} \
|
||||||
|
-D plugin-ice=enabled \
|
||||||
|
$PROJ_DIR $BUILD_DIR
|
||||||
|
}
|
||||||
|
|
||||||
|
build_meson()
|
||||||
|
{
|
||||||
|
meson compile -C $BUILD_DIR
|
||||||
|
meson install -C $BUILD_DIR
|
||||||
|
}
|
||||||
|
|
||||||
|
test_meson()
|
||||||
|
{
|
||||||
|
msg "Run tests"
|
||||||
|
meson test -C $BUILD_DIR
|
||||||
}
|
}
|
||||||
|
|
||||||
dist_install()
|
dist_install()
|
||||||
{
|
{
|
||||||
msg "Installing Dino in '$DIST_DIR'!"
|
_dist_arg=${1:-$DIST_DIR}
|
||||||
make install
|
|
||||||
|
msg "Generate dino-with-console.exe"
|
||||||
|
cp -f "$_dist_arg/bin/dino.exe" "$_dist_arg/bin/dino-with-console.exe"
|
||||||
|
# IMAGE_SUBSYSTEM_WINDOWS_CUI = 0x0003
|
||||||
|
# SUBSYSTEM_OFFSET = 0xDC (220)
|
||||||
|
printf '\x03\x00' | dd of="$_dist_arg/bin/dino-with-console.exe" bs=1 seek=220 count=2 conv=notrunc
|
||||||
|
|
||||||
msg "Copying MINGW64 dependencies"
|
msg "Copying MINGW64 dependencies"
|
||||||
cp /mingw64/bin/gdbus.exe "$DIST_DIR/bin"
|
cp /mingw64/bin/gdbus.exe "$_dist_arg/bin"
|
||||||
cp /mingw64/bin/gspawn-win64-helper.exe "$DIST_DIR/bin"
|
cp /mingw64/bin/gspawn-win64-helper.exe "$_dist_arg/bin"
|
||||||
|
|
||||||
cp /mingw64/bin/libcrypto-*-x64.dll "$DIST_DIR/bin/"
|
cp /mingw64/bin/libcrypto-*-x64.dll "$_dist_arg/bin/"
|
||||||
cp -r /mingw64/lib/gstreamer-1.0 "$DIST_DIR/lib"
|
cp -r /mingw64/lib/gstreamer-1.0 "$_dist_arg/lib"
|
||||||
mkdir -p "$DIST_DIR/lib/gdk-pixbuf-2.0/" && cp -r /mingw64/lib/gdk-pixbuf-2.0 "$DIST_DIR/lib/"
|
mkdir -p "$_dist_arg/lib/gdk-pixbuf-2.0/" && cp -r /mingw64/lib/gdk-pixbuf-2.0 "$_dist_arg/lib/"
|
||||||
mkdir -p "$DIST_DIR/lib/gio/" && cp -r /mingw64/lib/gio "$DIST_DIR/lib/"
|
mkdir -p "$_dist_arg/lib/gio/" && cp -r /mingw64/lib/gio "$_dist_arg/lib/"
|
||||||
|
|
||||||
list=`find "$DIST_DIR" -type f \( -name "*.exe" -o -name "*.dll" \) -exec \
|
list=`find "$_dist_arg" -type f \( -name "*.exe" -o -name "*.dll" \) -exec \
|
||||||
ntldd -R {} + | \
|
ntldd -R {} + | \
|
||||||
grep "mingw64" | \
|
grep "mingw64" | \
|
||||||
cut -f1 -d "=" | sort | uniq`
|
cut -f1 -d "=" | sort | uniq`
|
||||||
for a in $list; do
|
for a in $list; do
|
||||||
cp -fv "/mingw64/bin/$a" "$DIST_DIR/bin/"
|
cp -fv "/mingw64/bin/$a" "$_dist_arg/bin/"
|
||||||
done
|
done
|
||||||
|
|
||||||
msg "Removing debug information from all EXE and DLL files"
|
msg "Removing debug information from all EXE and DLL files"
|
||||||
find "$DIST_DIR" -iname "*.exe" -exec strip -s {} +
|
find "$_dist_arg" -iname "*.exe" -exec strip -s {} +
|
||||||
find "$DIST_DIR" -iname "*.dll" -exec strip -s {} +
|
find "$_dist_arg" -iname "*.dll" -exec strip -s {} +
|
||||||
|
|
||||||
find "$DIST_DIR" -iname "*.a" -exec rm {} +
|
find "$_dist_arg" -iname "*.a" -exec rm {} +
|
||||||
|
|
||||||
msg "Removing redudant header files"
|
msg "Removing redudant header files"
|
||||||
rm -rf "$DIST_DIR/include"
|
rm -rf "$_dist_arg/include"
|
||||||
|
|
||||||
msg "Copy LICENSE"
|
msg "Copy LICENSE"
|
||||||
cp -f "$PWD/LICENSE" "$DIST_DIR/LICENSE"
|
cp -f "$PWD/LICENSE" "$_dist_arg/LICENSE"
|
||||||
|
|
||||||
msg "Copy icons, themes, locales and fonts"
|
msg "Copy icons, themes, locales and fonts"
|
||||||
cp -f "$PWD/main/dino.ico" "$DIST_DIR/dino.ico"
|
cp -f "$PWD/main/dino.ico" "$_dist_arg/dino.ico"
|
||||||
cp -rf "/mingw64/share/xml" "$DIST_DIR/share"
|
cp -rf "/mingw64/share/xml" "$_dist_arg/share"
|
||||||
mkdir -p "$DIST_DIR/etc/fonts" && cp -r /mingw64/etc/fonts "$DIST_DIR/etc/"
|
mkdir -p "$_dist_arg/etc/fonts" && cp -r /mingw64/etc/fonts "$_dist_arg/etc/"
|
||||||
mkdir -p "$DIST_DIR/share/icons" && cp -r /mingw64/share/icons "$DIST_DIR/share/"
|
mkdir -p "$_dist_arg/share/icons" && cp -r /mingw64/share/icons "$_dist_arg/share/"
|
||||||
mkdir -p "$DIST_DIR/share/glib-2.0/schemas" && cp -rf /mingw64/share/glib-2.0/schemas "$DIST_DIR/share/glib-2.0/"
|
mkdir -p "$_dist_arg/share/glib-2.0/schemas" && cp -rf /mingw64/share/glib-2.0/schemas "$_dist_arg/share/glib-2.0/"
|
||||||
|
|
||||||
msg "Successfully installed!"
|
msg "Successfully installed!"
|
||||||
}
|
}
|
||||||
|
@ -140,24 +200,71 @@ build_installer()
|
||||||
|
|
||||||
clean()
|
clean()
|
||||||
{
|
{
|
||||||
rm -rf build "$DIST_DIR"
|
rm -rf $BUILD_DIR $DIST_DIR
|
||||||
msg "Build artifacts removed successfull!"
|
msg "Build artifacts removed successfull!"
|
||||||
}
|
}
|
||||||
|
|
||||||
help()
|
help()
|
||||||
{
|
{
|
||||||
cat << EOF
|
cat << EOF
|
||||||
usage: $0 [OPTION]
|
Script to build Dino for windows using cmake or meson build-system.
|
||||||
--prepare install build dependencies
|
By default it will be build using build directory
|
||||||
--configure configure the project
|
$BUILD_DIR
|
||||||
--build build the project
|
and installed to
|
||||||
--dist-install install the builded project
|
$DIST_DIR
|
||||||
--build-installer build installer (using NSIS)
|
|
||||||
--clean remove build artifacts
|
|
||||||
--help show this help
|
|
||||||
|
|
||||||
Running without parameters is equivalent to running:
|
Usage: $0 [option]
|
||||||
'--configure', '--build' and '--dist-install'
|
|
||||||
|
Note: you may set the multiple options, but be sure that they will be
|
||||||
|
processed sequentially (one-by-one), e.g. command
|
||||||
|
$0 -s meson -c -b
|
||||||
|
will run buld config and _after_ that run build using meson, while
|
||||||
|
$0 -c -b -s meson
|
||||||
|
will run cmake-based configure & build commands and the -s option
|
||||||
|
wont have any effect. And the one
|
||||||
|
$0 -b -s meson -c
|
||||||
|
is incorrect, as it willtry to run build(for cmake), then configure
|
||||||
|
with for meson build.
|
||||||
|
|
||||||
|
--help, -h
|
||||||
|
print this help message.
|
||||||
|
|
||||||
|
--set-buildsys, -s
|
||||||
|
set (specify) build system name to be used
|
||||||
|
possible options are: cmake or meson
|
||||||
|
|
||||||
|
--prepare, -p
|
||||||
|
install build dependencies. may be done once.
|
||||||
|
|
||||||
|
--configure, -c
|
||||||
|
configure build using selected build-system.
|
||||||
|
|
||||||
|
--build, -b
|
||||||
|
invoke build.
|
||||||
|
|
||||||
|
--test, -t
|
||||||
|
run tests.
|
||||||
|
|
||||||
|
--reconfig, -r
|
||||||
|
reconfigure project, if minor changes were
|
||||||
|
done to build config files but build has been
|
||||||
|
configured already (only for meson!).
|
||||||
|
|
||||||
|
--whipe, -w
|
||||||
|
remove build artifacts from $BUILD_DIR
|
||||||
|
|
||||||
|
--verbose, -v
|
||||||
|
verbose output enable.
|
||||||
|
|
||||||
|
--dist-install, -i
|
||||||
|
install the builded project along with its'
|
||||||
|
dependencies.
|
||||||
|
|
||||||
|
--build-installer
|
||||||
|
build installer (using NSIS)
|
||||||
|
|
||||||
|
Running without parameters will run configure, build & install
|
||||||
|
using cmake-based build-system as default one.
|
||||||
EOF
|
EOF
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,18 +272,62 @@ if [[ "$(uname)" != "MINGW64_NT"* ]]; then
|
||||||
fatal "This is not a MINGW64 environment!"
|
fatal "This is not a MINGW64 environment!"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
case $1 in
|
# no options provided,simply build with defaults
|
||||||
"--prepare" ) prepare ;;
|
if [[ $# == 0 ]]; then
|
||||||
"--configure" ) configure ;;
|
prepare
|
||||||
"--build" ) build ;;
|
configure_${build_sys}
|
||||||
"--dist-install" ) dist_install ;;
|
build_${build_sys}
|
||||||
"--build-installer") build_installer ;;
|
dist_install
|
||||||
"--clean" ) clean ;;
|
|
||||||
"--help" ) help ;;
|
exit 0
|
||||||
"" )
|
fi
|
||||||
configure
|
|
||||||
build
|
while [[ $# > 0 ]];
|
||||||
|
do
|
||||||
|
case $1 in
|
||||||
|
--prepare|-p)
|
||||||
|
prepare
|
||||||
|
;;
|
||||||
|
--configure|-c)
|
||||||
|
configure_${build_sys}
|
||||||
|
;;
|
||||||
|
--build|-b)
|
||||||
|
build_${build_sys}
|
||||||
|
;;
|
||||||
|
--test|-t)
|
||||||
|
test_${build_sys}
|
||||||
|
;;
|
||||||
|
--reconfig|-r)
|
||||||
|
configure_${build_sys} reconfig
|
||||||
|
;;
|
||||||
|
--whipe|-w)
|
||||||
|
clean
|
||||||
|
;;
|
||||||
|
--dist-install|-i)
|
||||||
dist_install
|
dist_install
|
||||||
;;
|
;;
|
||||||
*) fatal "Unknown argument!"
|
--verbose|-v)
|
||||||
esac
|
set -xv
|
||||||
|
;;
|
||||||
|
--help|-h)
|
||||||
|
help
|
||||||
|
exit 0;
|
||||||
|
;;
|
||||||
|
--build-installer)
|
||||||
|
build_installer
|
||||||
|
;;
|
||||||
|
--set-buildsys|-s)
|
||||||
|
if [ x"$2" != x"cmake" -a x"$2" != x"meson" ]; then
|
||||||
|
fatal "Improper build system selected: ${2}!"
|
||||||
|
exit 1;
|
||||||
|
fi
|
||||||
|
build_sys=$2
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
-*)
|
||||||
|
echo "Unknown option $1"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
|
|
@ -47,7 +47,7 @@ function(_compute_version_from_git)
|
||||||
return()
|
return()
|
||||||
endif (NOT git_result EQUAL 0)
|
endif (NOT git_result EQUAL 0)
|
||||||
|
|
||||||
if (git_tag MATCHES "^v?([0-9]+[.]?[0-9]*[.]?[0-9]*)(-[.0-9A-Za-z-]+)?([+][.0-9A-Za-z-]+)?$")
|
if (git_tag MATCHES "^v?([0-9]+[.]?[0-9]*[.]?[0-9]*[.]?[0-9]*)(-[.0-9A-Za-z-]+)?([+][.0-9A-Za-z-]+)?$")
|
||||||
set(VERSION_LAST_RELEASE "${CMAKE_MATCH_1}")
|
set(VERSION_LAST_RELEASE "${CMAKE_MATCH_1}")
|
||||||
else ()
|
else ()
|
||||||
return()
|
return()
|
||||||
|
|
11
cmake/FindGstWebrtcDsp.cmake
Normal file
11
cmake/FindGstWebrtcDsp.cmake
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
find_library(GstWebrtcDsp_LIBRARY gstwebrtcdsp PATH_SUFFIXES gstreamer-1.0)
|
||||||
|
|
||||||
|
if(GstWebrtcDsp_LIBRARY_FOUND)
|
||||||
|
find_package(Gst)
|
||||||
|
set(GstWebrtcDsp_VERSION ${Gst_VERSION})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
include(FindPackageHandleStandardArgs)
|
||||||
|
find_package_handle_standard_args(GstWebrtcDsp
|
||||||
|
REQUIRED_VARS GstWebrtcDsp_LIBRARY
|
||||||
|
VERSION_VAR GstWebrtcDsp_VERSION)
|
|
@ -1,12 +0,0 @@
|
||||||
include(PkgConfigWithFallback)
|
|
||||||
find_pkg_config_with_fallback(WebRTCAudioProcessing
|
|
||||||
PKG_CONFIG_NAME webrtc-audio-processing
|
|
||||||
LIB_NAMES webrtc_audio_processing
|
|
||||||
INCLUDE_NAMES webrtc/modules/audio_processing/include/audio_processing.h
|
|
||||||
INCLUDE_DIR_SUFFIXES webrtc-audio-processing webrtc_audio_processing
|
|
||||||
)
|
|
||||||
|
|
||||||
include(FindPackageHandleStandardArgs)
|
|
||||||
find_package_handle_standard_args(WebRTCAudioProcessing
|
|
||||||
REQUIRED_VARS WebRTCAudioProcessing_LIBRARY
|
|
||||||
VERSION_VAR WebRTCAudioProcessing_VERSION)
|
|
34
cmake/Packing.cmake
Normal file
34
cmake/Packing.cmake
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
# This is a package creation module using CPack.
|
||||||
|
# Currently only DEB package generation is supported.
|
||||||
|
|
||||||
|
set(CPACK_PACKAGE_NAME dino-plus)
|
||||||
|
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY
|
||||||
|
"modern XMPP/Jabber client software, based on Dino.
|
||||||
|
Dino+ is a fork of Dino, a modern XMPP/Jabber client
|
||||||
|
written in Vala using GTK+, which includes a few
|
||||||
|
relatively minor but important quality-of-life features.")
|
||||||
|
|
||||||
|
set(CPACK_VERBATIM_VARIABLES YES)
|
||||||
|
set(CPACK_PACKAGE_FILE_NAME ${CPACK_PACKAGE_NAME})
|
||||||
|
set(CPACK_PACKAGE_INSTALL_DIRECTORY ${CPACK_PACKAGE_NAME})
|
||||||
|
set(CPACK_OUTPUT_FILE_PREFIX "${CMAKE_SOURCE_DIR}/_packages")
|
||||||
|
set(CPACK_PACKAGE_VERSION ${VERSION_FULL})
|
||||||
|
set(CPACK_PACKAGE_HOMEPAGE_URL "https://github.com/mxlgv/dino")
|
||||||
|
set(CPACK_PACKAGE_CONTACT "maxlogaev@proton.me")
|
||||||
|
set(CPACK_COMPONENTS_GROUPING ALL_COMPONENTS_IN_ONE)
|
||||||
|
set(CPACK_STRIP_FILES TRUE)
|
||||||
|
|
||||||
|
# For DEB only
|
||||||
|
set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Maxim Logaev <${CPACK_PACKAGE_CONTACT}>")
|
||||||
|
set(CPACK_DEB_COMPONENT_INSTALL YES)
|
||||||
|
set(CPACK_DEBIAN_PACKAGE_SECTION "net")
|
||||||
|
set(CPACK_DEBIAN_PACKAGE_CONFLICTS "dino-im, dino-im-common")
|
||||||
|
set(CPACK_DEBIAN_PACKAGE_RECOMMENDS "ca-certificates, dbus, fonts-noto-color-emoji, network-manager")
|
||||||
|
set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)
|
||||||
|
set(CPACK_DEBIAN_PACKAGE_GENERATE_SHLIBS ON)
|
||||||
|
set(CPACK_DEBIAN_PACKAGE_GENERATE_SHLIBS_POLICY ">=")
|
||||||
|
|
||||||
|
install(FILES ${CMAKE_SOURCE_DIR}/LICENSE_SHORT DESTINATION ${SHARE_INSTALL_PREFIX}/doc/${CPACK_PACKAGE_NAME} RENAME copyright)
|
||||||
|
install(FILES ${CMAKE_SOURCE_DIR}/README.md DESTINATION ${SHARE_INSTALL_PREFIX}/doc/${CPACK_PACKAGE_NAME})
|
||||||
|
|
||||||
|
include(CPack)
|
12
configure
vendored
12
configure
vendored
|
@ -1,7 +1,7 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
OPTS=`getopt -o "h" --long \
|
OPTS=`getopt -o "h" --long \
|
||||||
help,fetch-only,no-debug,disable-fast-vapi,with-tests,release,with-libsoup3,\
|
help,fetch-only,no-debug,disable-fast-vapi,with-tests,release,with-libsoup3,without-webrtcdsp,\
|
||||||
enable-plugin:,disable-plugin:,\
|
enable-plugin:,disable-plugin:,\
|
||||||
prefix:,program-prefix:,exec-prefix:,lib-suffix:,\
|
prefix:,program-prefix:,exec-prefix:,lib-suffix:,\
|
||||||
bindir:,libdir:,includedir:,datadir:,\
|
bindir:,libdir:,includedir:,datadir:,\
|
||||||
|
@ -15,12 +15,13 @@ eval set -- "$OPTS"
|
||||||
PREFIX=${PREFIX:-/usr/local}
|
PREFIX=${PREFIX:-/usr/local}
|
||||||
ENABLED_PLUGINS=
|
ENABLED_PLUGINS=
|
||||||
DISABLED_PLUGINS=
|
DISABLED_PLUGINS=
|
||||||
BUILD_TESTS=
|
BUILD_TESTS=no
|
||||||
BUILD_TYPE=Debug
|
BUILD_TYPE=Debug
|
||||||
DISABLE_FAST_VAPI=
|
DISABLE_FAST_VAPI=
|
||||||
LIB_SUFFIX=
|
LIB_SUFFIX=
|
||||||
NO_DEBUG=
|
NO_DEBUG=
|
||||||
USE_SOUP3=
|
USE_SOUP3=
|
||||||
|
PLUGIN_RTP_WEBRTC_AUDIO_PROCESSING=yes
|
||||||
|
|
||||||
EXEC_PREFIX=
|
EXEC_PREFIX=
|
||||||
BINDIR=
|
BINDIR=
|
||||||
|
@ -54,6 +55,7 @@ Configuration:
|
||||||
--no-debug Build without debug symbols
|
--no-debug Build without debug symbols
|
||||||
--release Configure to build an optimized release version
|
--release Configure to build an optimized release version
|
||||||
--with-libsoup3 Build with libsoup-3.0
|
--with-libsoup3 Build with libsoup-3.0
|
||||||
|
--without-webrtcdsp Build without WebRTC audio processing
|
||||||
--with-tests Also build tests.
|
--with-tests Also build tests.
|
||||||
|
|
||||||
Plugin configuration:
|
Plugin configuration:
|
||||||
|
@ -109,6 +111,7 @@ while true; do
|
||||||
--valac-flags ) VALACFLAGS="$2"; shift; shift ;;
|
--valac-flags ) VALACFLAGS="$2"; shift; shift ;;
|
||||||
--lib-suffix ) LIB_SUFFIX="$2"; shift; shift ;;
|
--lib-suffix ) LIB_SUFFIX="$2"; shift; shift ;;
|
||||||
--with-libsoup3 ) USE_SOUP3=yes; shift ;;
|
--with-libsoup3 ) USE_SOUP3=yes; shift ;;
|
||||||
|
--without-webrtcdsp ) PLUGIN_RTP_WEBRTC_AUDIO_PROCESSING=no; shift ;;
|
||||||
--disable-fast-vapi ) DISABLE_FAST_VAPI=yes; shift ;;
|
--disable-fast-vapi ) DISABLE_FAST_VAPI=yes; shift ;;
|
||||||
--no-debug ) NO_DEBUG=yes; shift ;;
|
--no-debug ) NO_DEBUG=yes; shift ;;
|
||||||
--release ) BUILD_TYPE=RelWithDebInfo; shift ;;
|
--release ) BUILD_TYPE=RelWithDebInfo; shift ;;
|
||||||
|
@ -207,7 +210,7 @@ cmake -G "$cmake_type" \
|
||||||
-DCMAKE_BUILD_TYPE="$BUILD_TYPE" \
|
-DCMAKE_BUILD_TYPE="$BUILD_TYPE" \
|
||||||
-DENABLED_PLUGINS="$ENABLED_PLUGINS" \
|
-DENABLED_PLUGINS="$ENABLED_PLUGINS" \
|
||||||
-DDISABLED_PLUGINS="$DISABLED_PLUGINS" \
|
-DDISABLED_PLUGINS="$DISABLED_PLUGINS" \
|
||||||
-DBUILD_TESTS="$BUILD_TESTS" \
|
-DBUILD_TESTING="$BUILD_TESTS" \
|
||||||
-DUSE_SOUP3="$USE_SOUP3" \
|
-DUSE_SOUP3="$USE_SOUP3" \
|
||||||
-DVALA_EXECUTABLE="$VALAC" \
|
-DVALA_EXECUTABLE="$VALAC" \
|
||||||
-DCMAKE_VALA_FLAGS="$VALACFLAGS" \
|
-DCMAKE_VALA_FLAGS="$VALACFLAGS" \
|
||||||
|
@ -219,6 +222,7 @@ cmake -G "$cmake_type" \
|
||||||
-DBIN_INSTALL_DIR="$BINDIR" \
|
-DBIN_INSTALL_DIR="$BINDIR" \
|
||||||
-DINCLUDE_INSTALL_DIR="$INCLUDEDIR" \
|
-DINCLUDE_INSTALL_DIR="$INCLUDEDIR" \
|
||||||
-DLIB_INSTALL_DIR="$LIBDIR" \
|
-DLIB_INSTALL_DIR="$LIBDIR" \
|
||||||
|
-DPLUGIN_RTP_WEBRTC_AUDIO_PROCESSING="$PLUGIN_RTP_WEBRTC_AUDIO_PROCESSING" \
|
||||||
-Wno-dev \
|
-Wno-dev \
|
||||||
.. || exit 9
|
.. || exit 9
|
||||||
|
|
||||||
|
@ -238,8 +242,6 @@ default:
|
||||||
@sh -c "cd build; $exec_command"
|
@sh -c "cd build; $exec_command"
|
||||||
distclean: clean uninstall
|
distclean: clean uninstall
|
||||||
|
|
||||||
test: default
|
|
||||||
echo "make test not yet supported"
|
|
||||||
%:
|
%:
|
||||||
@sh -c "cd build; $exec_command \"\$@\""
|
@sh -c "cd build; $exec_command \"\$@\""
|
||||||
EOF
|
EOF
|
||||||
|
|
|
@ -22,6 +22,8 @@ GENERATE_VAPI
|
||||||
crypto-vala
|
crypto-vala
|
||||||
GENERATE_HEADER
|
GENERATE_HEADER
|
||||||
crypto-vala
|
crypto-vala
|
||||||
|
DEFINITIONS
|
||||||
|
GCRYPT
|
||||||
)
|
)
|
||||||
|
|
||||||
add_custom_target(crypto-vala-vapi
|
add_custom_target(crypto-vala-vapi
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
dependencies = [
|
dependencies = [
|
||||||
dep_gio,
|
dep_gio,
|
||||||
dep_glib,
|
dep_glib,
|
||||||
dep_libgcrypt,
|
dep_libgcrypt_or_openssl,
|
||||||
dep_libsrtp2,
|
dep_libsrtp2,
|
||||||
]
|
]
|
||||||
sources = files(
|
sources = files(
|
||||||
|
@ -17,6 +17,11 @@ c_args = [
|
||||||
vala_args = [
|
vala_args = [
|
||||||
'--vapidir', meson.current_source_dir() / 'vapi',
|
'--vapidir', meson.current_source_dir() / 'vapi',
|
||||||
]
|
]
|
||||||
|
if crypto_backend == 'openssl'
|
||||||
|
vala_args += ['--pkg', 'openssl'] # Work around https://github.com/mesonbuild/meson/issues/2103.
|
||||||
|
elif crypto_backend == 'gnutls'
|
||||||
|
vala_args += ['-D', 'GCRYPT']
|
||||||
|
endif
|
||||||
lib_crypto_vala = library('crypto-vala', sources, c_args: c_args, vala_args: vala_args, dependencies: dependencies, version: '0.0', install: true, install_dir: [true, true, true])
|
lib_crypto_vala = library('crypto-vala', sources, c_args: c_args, vala_args: vala_args, dependencies: dependencies, version: '0.0', install: true, install_dir: [true, true, true])
|
||||||
dep_crypto_vala = declare_dependency(link_with: lib_crypto_vala, include_directories: include_directories('.'))
|
dep_crypto_vala = declare_dependency(link_with: lib_crypto_vala, include_directories: include_directories('.'))
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,24 @@
|
||||||
namespace Crypto {
|
namespace Crypto {
|
||||||
public class SymmetricCipher {
|
public class SymmetricCipher {
|
||||||
|
#if GCRYPT
|
||||||
private GCrypt.Cipher.Cipher cipher;
|
private GCrypt.Cipher.Cipher cipher;
|
||||||
|
#else
|
||||||
|
bool is_encryption;
|
||||||
|
private OpenSSL.EVP.CipherContext? cipher;
|
||||||
|
#endif
|
||||||
|
|
||||||
public static bool supports(string algo_name) {
|
public static bool supports(string algo_name) {
|
||||||
|
#if GCRYPT
|
||||||
GCrypt.Cipher.Algorithm algo;
|
GCrypt.Cipher.Algorithm algo;
|
||||||
GCrypt.Cipher.Mode mode;
|
GCrypt.Cipher.Mode mode;
|
||||||
GCrypt.Cipher.Flag flags;
|
GCrypt.Cipher.Flag flags;
|
||||||
return parse(algo_name, out algo, out mode, out flags);
|
return parse(algo_name, out algo, out mode, out flags);
|
||||||
|
#else
|
||||||
|
return algo_name == "AES-GCM";
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if GCRYPT
|
||||||
private static unowned string mode_to_string(GCrypt.Cipher.Mode mode) {
|
private static unowned string mode_to_string(GCrypt.Cipher.Mode mode) {
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case GCrypt.Cipher.Mode.ECB: return "ECB";
|
case GCrypt.Cipher.Mode.ECB: return "ECB";
|
||||||
|
@ -95,8 +105,18 @@ public class SymmetricCipher {
|
||||||
return algo.to_string();
|
return algo.to_string();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
public SymmetricCipher(string algo_name) throws Error {
|
public SymmetricCipher.encryption(string algo_name) throws Error {
|
||||||
|
this.initialize(algo_name, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SymmetricCipher.decryption(string algo_name) throws Error {
|
||||||
|
this.initialize(algo_name, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private SymmetricCipher.initialize(string algo_name, bool is_encryption) throws Error {
|
||||||
|
#if GCRYPT
|
||||||
GCrypt.Cipher.Algorithm algo;
|
GCrypt.Cipher.Algorithm algo;
|
||||||
GCrypt.Cipher.Mode mode;
|
GCrypt.Cipher.Mode mode;
|
||||||
GCrypt.Cipher.Flag flags;
|
GCrypt.Cipher.Flag flags;
|
||||||
|
@ -105,48 +125,157 @@ public class SymmetricCipher {
|
||||||
} else {
|
} else {
|
||||||
throw new Error.ILLEGAL_ARGUMENTS(@"The algorithm $algo_name is not supported");
|
throw new Error.ILLEGAL_ARGUMENTS(@"The algorithm $algo_name is not supported");
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
if (algo_name == "AES-GCM") {
|
||||||
|
this.openssl(is_encryption);
|
||||||
|
} else {
|
||||||
|
throw new Error.ILLEGAL_ARGUMENTS(@"The algorithm $algo_name is not supported");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if GCRYPT
|
||||||
private SymmetricCipher.gcrypt(GCrypt.Cipher.Algorithm algo, GCrypt.Cipher.Mode mode, GCrypt.Cipher.Flag flags) throws Error {
|
private SymmetricCipher.gcrypt(GCrypt.Cipher.Algorithm algo, GCrypt.Cipher.Mode mode, GCrypt.Cipher.Flag flags) throws Error {
|
||||||
may_throw_gcrypt_error(GCrypt.Cipher.Cipher.open(out this.cipher, algo, mode, flags));
|
may_throw_gcrypt_error(GCrypt.Cipher.Cipher.open(out this.cipher, algo, mode, flags));
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
private SymmetricCipher.openssl(bool is_encryption) throws Error {
|
||||||
|
this.is_encryption = is_encryption;
|
||||||
|
cipher = new OpenSSL.EVP.CipherContext();
|
||||||
|
if (is_encryption) {
|
||||||
|
if (cipher.encrypt_init(OpenSSL.EVP.aes_128_gcm(), null, null, null) != 1) {
|
||||||
|
openssl_error();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (cipher.decrypt_init(OpenSSL.EVP.aes_128_gcm(), null, null, null) != 1) {
|
||||||
|
openssl_error();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
public void set_key(uint8[] key) throws Error {
|
public void set_key(uint8[] key) throws Error {
|
||||||
|
#if GCRYPT
|
||||||
may_throw_gcrypt_error(cipher.set_key(key));
|
may_throw_gcrypt_error(cipher.set_key(key));
|
||||||
|
#else
|
||||||
|
if (key.length != 16) {
|
||||||
|
throw new Crypto.Error.ILLEGAL_ARGUMENTS("key length must be 16 for AES-GCM");
|
||||||
|
}
|
||||||
|
if (is_encryption) {
|
||||||
|
if (cipher.encrypt_init(null, null, key, null) != 1) {
|
||||||
|
openssl_error();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (cipher.decrypt_init(null, null, key, null) != 1) {
|
||||||
|
openssl_error();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
public void set_iv(uint8[] iv) throws Error {
|
public void set_iv(uint8[] iv) throws Error {
|
||||||
|
#if GCRYPT
|
||||||
may_throw_gcrypt_error(cipher.set_iv(iv));
|
may_throw_gcrypt_error(cipher.set_iv(iv));
|
||||||
|
#else
|
||||||
|
if (iv.length != 12) {
|
||||||
|
throw new Crypto.Error.ILLEGAL_ARGUMENTS("intialization vector must be of length 16 for AES-GCM");
|
||||||
}
|
}
|
||||||
|
if (is_encryption) {
|
||||||
public void set_counter_vector(uint8[] ctr) throws Error {
|
if (cipher.encrypt_init(null, null, null, iv) != 1) {
|
||||||
may_throw_gcrypt_error(cipher.set_counter_vector(ctr));
|
openssl_error();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (cipher.decrypt_init(null, null, null, iv) != 1) {
|
||||||
|
openssl_error();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
public void reset() throws Error {
|
public void reset() throws Error {
|
||||||
|
#if GCRYPT
|
||||||
may_throw_gcrypt_error(cipher.reset());
|
may_throw_gcrypt_error(cipher.reset());
|
||||||
|
#else
|
||||||
|
throw new Crypto.Error.ILLEGAL_ARGUMENTS("can't reset OpenSSL cipher context");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
public uint8[] get_tag(size_t taglen) throws Error {
|
public uint8[] get_tag(size_t taglen) throws Error {
|
||||||
uint8[] tag = new uint8[taglen];
|
uint8[] tag = new uint8[taglen];
|
||||||
|
#if GCRYPT
|
||||||
may_throw_gcrypt_error(cipher.get_tag(tag));
|
may_throw_gcrypt_error(cipher.get_tag(tag));
|
||||||
|
#else
|
||||||
|
if (!is_encryption) {
|
||||||
|
throw new Crypto.Error.ILLEGAL_ARGUMENTS("can't call get_tag on decryption context");
|
||||||
|
}
|
||||||
|
uint8[] empty = new uint8[0];
|
||||||
|
int empty_len = 0;
|
||||||
|
if (cipher.encrypt_final(empty, out empty_len) != 1) {
|
||||||
|
openssl_error();
|
||||||
|
}
|
||||||
|
if (empty_len != 0) {
|
||||||
|
throw new Crypto.Error.ILLEGAL_ARGUMENTS("get_tag called on a stream with remaining data");
|
||||||
|
}
|
||||||
|
if (cipher.ctrl(OpenSSL.EVP.CTRL_GCM_GET_TAG, (int)taglen, tag) != 1) {
|
||||||
|
openssl_error();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
return tag;
|
return tag;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void check_tag(uint8[] tag) throws Error {
|
public void check_tag(uint8[] tag) throws Error {
|
||||||
|
#if GCRYPT
|
||||||
may_throw_gcrypt_error(cipher.check_tag(tag));
|
may_throw_gcrypt_error(cipher.check_tag(tag));
|
||||||
|
#else
|
||||||
|
if (is_encryption) {
|
||||||
|
throw new Crypto.Error.ILLEGAL_ARGUMENTS("can't call check_tag on encryption context");
|
||||||
|
}
|
||||||
|
if (cipher.ctrl(OpenSSL.EVP.CTRL_GCM_SET_TAG, tag.length, tag) != 1) {
|
||||||
|
openssl_error();
|
||||||
|
}
|
||||||
|
uint8[] empty = new uint8[0];
|
||||||
|
int empty_len = 0;
|
||||||
|
if (cipher.decrypt_final(empty, out empty_len) != 1) {
|
||||||
|
openssl_error();
|
||||||
|
}
|
||||||
|
if (empty_len != 0) {
|
||||||
|
throw new Crypto.Error.ILLEGAL_ARGUMENTS("check_tag called on a stream with remaining data");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
public void encrypt(uint8[] output, uint8[] input) throws Error {
|
public void encrypt(uint8[] output, uint8[] input) throws Error {
|
||||||
|
#if GCRYPT
|
||||||
may_throw_gcrypt_error(cipher.encrypt(output, input));
|
may_throw_gcrypt_error(cipher.encrypt(output, input));
|
||||||
|
#else
|
||||||
|
if (!is_encryption) {
|
||||||
|
throw new Crypto.Error.ILLEGAL_ARGUMENTS("can't call encrypt on decryption context");
|
||||||
|
}
|
||||||
|
int output_length = output.length;
|
||||||
|
if (cipher.encrypt_update(output, out output_length, input) != 1) {
|
||||||
|
openssl_error();
|
||||||
|
}
|
||||||
|
if (output_length != output.length) {
|
||||||
|
throw new Crypto.Error.ILLEGAL_ARGUMENTS("invalid output array length");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
public void decrypt(uint8[] output, uint8[] input) throws Error {
|
public void decrypt(uint8[] output, uint8[] input) throws Error {
|
||||||
|
#if GCRYPT
|
||||||
may_throw_gcrypt_error(cipher.decrypt(output, input));
|
may_throw_gcrypt_error(cipher.decrypt(output, input));
|
||||||
|
#else
|
||||||
|
if (is_encryption) {
|
||||||
|
throw new Crypto.Error.ILLEGAL_ARGUMENTS("can't call decrypt on encryption context");
|
||||||
}
|
}
|
||||||
|
int output_length = output.length;
|
||||||
public void sync() throws Error {
|
if (cipher.decrypt_update(output, out output_length, input) != 1) {
|
||||||
may_throw_gcrypt_error(cipher.sync());
|
openssl_error();
|
||||||
|
}
|
||||||
|
if (output_length != output.length) {
|
||||||
|
throw new Crypto.Error.ILLEGAL_ARGUMENTS("invalid output array length");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,13 +3,20 @@ namespace Crypto {
|
||||||
public errordomain Error {
|
public errordomain Error {
|
||||||
ILLEGAL_ARGUMENTS,
|
ILLEGAL_ARGUMENTS,
|
||||||
GCRYPT,
|
GCRYPT,
|
||||||
|
OPENSSL,
|
||||||
AUTHENTICATION_FAILED,
|
AUTHENTICATION_FAILED,
|
||||||
UNKNOWN
|
UNKNOWN
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if GCRYPT
|
||||||
internal void may_throw_gcrypt_error(GCrypt.Error e) throws Error {
|
internal void may_throw_gcrypt_error(GCrypt.Error e) throws Error {
|
||||||
if (((int)e) != 0) {
|
if (((int)e) != 0) {
|
||||||
throw new Crypto.Error.GCRYPT(e.to_string());
|
throw new Crypto.Error.GCRYPT(e.to_string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
internal void openssl_error() throws Error {
|
||||||
|
throw new Crypto.Error.OPENSSL(OpenSSL.ERR.reason_error_string(OpenSSL.ERR.get_error()));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
|
@ -1,5 +1,9 @@
|
||||||
namespace Crypto {
|
namespace Crypto {
|
||||||
public static void randomize(uint8[] buffer) {
|
public static void randomize(uint8[] buffer) {
|
||||||
|
#if GCRYPT
|
||||||
GCrypt.Random.randomize(buffer);
|
GCrypt.Random.randomize(buffer);
|
||||||
|
#else
|
||||||
|
OpenSSL.RAND.bytes(buffer);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
822
crypto-vala/vapi/openssl.vapi
Normal file
822
crypto-vala/vapi/openssl.vapi
Normal file
|
@ -0,0 +1,822 @@
|
||||||
|
/* OpenSSL Vala Bindings
|
||||||
|
* Copyright 2020 Zuhong Tao <taozuhong@gmail>
|
||||||
|
* Copyright 2016 Guillaume Poirier-Morency <guillaumepoiriermorency@gmail>
|
||||||
|
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||||
|
* this file except in compliance with the License. You can obtain a copy
|
||||||
|
* in the file LICENSE in the source distribution or at
|
||||||
|
* https://www.openssl.org/source/license.html
|
||||||
|
*/
|
||||||
|
|
||||||
|
[CCode (cprefix = "")]
|
||||||
|
namespace OpenSSL
|
||||||
|
{
|
||||||
|
[CCode (cprefix = "AES_", lower_case_cprefix = "AES_", cheader_filename = "openssl/aes.h")]
|
||||||
|
namespace AES
|
||||||
|
{
|
||||||
|
public const int BLOCK_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Compact]
|
||||||
|
[CCode (cname = "ENGINE", lower_case_cprefix = "ENGINE_", cprefix = "ENGINE_", cheader_filename = "openssl/engine.h", free_function = "ENGINE_free")]
|
||||||
|
public class Engine {
|
||||||
|
[CCode (cname = "ENGINE_new")]
|
||||||
|
public Engine ();
|
||||||
|
[CCode (cname = "ENGINE_by_id")]
|
||||||
|
public Engine.by_id (string id);
|
||||||
|
[CCode (cname = "ENGINE_get_default_RSA")]
|
||||||
|
public Engine.get_default_RSA ();
|
||||||
|
[CCode (cname = "ENGINE_get_default_DSA")]
|
||||||
|
public Engine.get_default_DSA ();
|
||||||
|
[CCode (cname = "ENGINE_get_default_DH")]
|
||||||
|
public Engine.get_default_DH ();
|
||||||
|
[CCode (cname = "ENGINE_get_default_RAND")]
|
||||||
|
public Engine.get_default_RAND ();
|
||||||
|
[CCode (cname = "ENGINE_get_cipher_engine")]
|
||||||
|
public Engine.get_cipher_engine (int nid);
|
||||||
|
[CCode (cname = "ENGINE_get_digest_engine")]
|
||||||
|
public Engine.get_digest_engine (int nid);
|
||||||
|
|
||||||
|
public int init ();
|
||||||
|
public int finish ();
|
||||||
|
public int set_default (uint flags);
|
||||||
|
public int set_default_RSA ();
|
||||||
|
public int set_default_DSA ();
|
||||||
|
public int set_default_DH ();
|
||||||
|
public int set_default_RAND ();
|
||||||
|
public int set_default_ciphers ();
|
||||||
|
public int set_default_digests ();
|
||||||
|
public int set_default_string (string list);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
[CCode (cprefix = "NID_", cheader_filename = "openssl/objects.h")]
|
||||||
|
public enum NID
|
||||||
|
{
|
||||||
|
sha256
|
||||||
|
}
|
||||||
|
|
||||||
|
[Compact]
|
||||||
|
[CCode (cname = "BIO_METHOD", cheader_filename = "openssl/bio.h", free_function = "BIO_meth_free")]
|
||||||
|
public class BIOMethod
|
||||||
|
{
|
||||||
|
public const int BIO_TYPE_DESCRIPTOR;
|
||||||
|
public const int BIO_TYPE_FILTER;
|
||||||
|
public const int BIO_TYPE_SOURCE_SINK;
|
||||||
|
public const int BIO_TYPE_NONE;
|
||||||
|
public const int BIO_TYPE_MEM;
|
||||||
|
public const int BIO_TYPE_FILE;
|
||||||
|
public const int BIO_TYPE_FD;
|
||||||
|
public const int BIO_TYPE_SOCKET;
|
||||||
|
public const int BIO_TYPE_NULL;
|
||||||
|
public const int BIO_TYPE_SSL;
|
||||||
|
public const int BIO_TYPE_MD;
|
||||||
|
public const int BIO_TYPE_BUFFER;
|
||||||
|
public const int BIO_TYPE_CIPHER;
|
||||||
|
public const int BIO_TYPE_BASE64;
|
||||||
|
public const int BIO_TYPE_CONNECT;
|
||||||
|
public const int BIO_TYPE_ACCEPT;
|
||||||
|
public const int BIO_TYPE_NBIO_TEST;
|
||||||
|
public const int BIO_TYPE_NULL_FILTER;
|
||||||
|
public const int BIO_TYPE_BIO;
|
||||||
|
public const int BIO_TYPE_LINEBUFFER;
|
||||||
|
public const int BIO_TYPE_DGRAM;
|
||||||
|
public const int BIO_TYPE_ASN1;
|
||||||
|
public const int BIO_TYPE_COMP;
|
||||||
|
public const int BIO_TYPE_DGRAM_SCTP;
|
||||||
|
|
||||||
|
[CCode (cname = "BIO_meth_new")]
|
||||||
|
public BIOMethod (int type, string name);
|
||||||
|
|
||||||
|
[CCode (cname = "BIO_get_new_index")]
|
||||||
|
public int get_new_index ();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Compact]
|
||||||
|
[CCode (lower_case_cprefix = "BUF_MEM_", cheader_filename = "openssl/buffer.h", free_function = "BUF_MEM_free")]
|
||||||
|
public class Buffer {
|
||||||
|
|
||||||
|
[CCode (cname = "BUF_MEM_new")]
|
||||||
|
public Buffer ();
|
||||||
|
|
||||||
|
[CCode (cname = "BUF_MEM_new_ex")]
|
||||||
|
public Buffer.with_flags ();
|
||||||
|
|
||||||
|
public int grow (int len);
|
||||||
|
public size_t grow_clean (size_t len);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Compact]
|
||||||
|
[CCode (lower_case_cprefix = "BIO_", cheader_filename = "openssl/bio.h", free_function = "BIO_free")]
|
||||||
|
public class BIO
|
||||||
|
{
|
||||||
|
public const int NOCLOSE;
|
||||||
|
|
||||||
|
public static unowned BIOMethod s_mem ();
|
||||||
|
public static unowned BIOMethod s_secmem ();
|
||||||
|
|
||||||
|
public BIO (BIOMethod type);
|
||||||
|
|
||||||
|
[CCode (cname = "BIO_new_file")]
|
||||||
|
public BIO.with_file (string filename, string mode);
|
||||||
|
|
||||||
|
[CCode (cname = "BIO_new_fp")]
|
||||||
|
public BIO.with_stream (GLib.FileStream stream, int flags);
|
||||||
|
|
||||||
|
[CCode (cname = "BIO_new_mem_buf")]
|
||||||
|
public BIO.with_buffer (uint8[] buf);
|
||||||
|
|
||||||
|
public int read_filename (string name);
|
||||||
|
public int write_filename (string name);
|
||||||
|
public int append_filename (string name);
|
||||||
|
public int rw_filename (string name);
|
||||||
|
|
||||||
|
public int set_mem_eof_return (int v);
|
||||||
|
public long get_mem_data ([CCode (array_length = false)] out uint8[] pp);
|
||||||
|
public int set_mem_buf (Buffer bm, int c);
|
||||||
|
public int get_mem_ptr (out Buffer pp);
|
||||||
|
|
||||||
|
public int set (BIOMethod type);
|
||||||
|
public int read (uint8[] data);
|
||||||
|
public int write (uint8[] data);
|
||||||
|
|
||||||
|
[PrintfFormat]
|
||||||
|
public int printf (string format, ...);
|
||||||
|
|
||||||
|
[PrintfFormat]
|
||||||
|
public int vprintf (string format, va_list args);
|
||||||
|
|
||||||
|
[PrintfFormat]
|
||||||
|
public static int snprintf (uint8[] buf, string format, ...);
|
||||||
|
|
||||||
|
[PrintfFormat]
|
||||||
|
public static int vsnprintf (uint8[] buf, string format, va_list args);
|
||||||
|
|
||||||
|
public int reset ();
|
||||||
|
public int seek (int ofs);
|
||||||
|
public int pending ();
|
||||||
|
public int wpending ();
|
||||||
|
public int flush ();
|
||||||
|
public int eof ();
|
||||||
|
public int tell ();
|
||||||
|
public int set_close (long flag);
|
||||||
|
public int get_close ();
|
||||||
|
public long ctrl (int cmd, long larg, [CCode (array_length = false)] uint8[] parg);
|
||||||
|
|
||||||
|
public int read_ex (uint8[] data, out size_t readbytes);
|
||||||
|
public int write_ex (uint8[] data, out size_t written);
|
||||||
|
}
|
||||||
|
|
||||||
|
[CCode (lower_case_cprefix = "CRYPTO_", cheader_filename = "openssl/crypto.h")]
|
||||||
|
namespace Crypto
|
||||||
|
{
|
||||||
|
public int memcmp (void* v1, void* v2, size_t n);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Compact]
|
||||||
|
[CCode (cname = "ASN1_PCTX", lower_case_cprefix = "ASN1_PCTX_", free_function = "ASN1_PCTX_free")]
|
||||||
|
public class ASN1_PCTX {
|
||||||
|
public ASN1_PCTX ();
|
||||||
|
|
||||||
|
public ulong get_flags ();
|
||||||
|
public void set_flags (ulong flags);
|
||||||
|
public ulong get_nm_flags ();
|
||||||
|
public void set_nm_flags (ulong flags);
|
||||||
|
public ulong get_cert_flags ();
|
||||||
|
public void set_cert_flags (ulong flags);
|
||||||
|
|
||||||
|
public ulong get_oid_flags ();
|
||||||
|
public void set_oid_flags (ulong flags);
|
||||||
|
public ulong get_str_flags ();
|
||||||
|
public void set_str_flags (ulong flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Compact]
|
||||||
|
[CCode (cname = "ASN1_SCTX", lower_case_cprefix = "ASN1_SCTX_", free_function = "ASN1_SCTX_free")]
|
||||||
|
public class ASN1_SCTX {
|
||||||
|
public ASN1_SCTX ();
|
||||||
|
|
||||||
|
public ulong get_flags ();
|
||||||
|
}
|
||||||
|
|
||||||
|
[CCode (cprefix = "EVP_", lower_case_cprefix = "EVP_", cheader_filename = "openssl/evp.h")]
|
||||||
|
namespace EVP
|
||||||
|
{
|
||||||
|
public const int CIPH_STREAM_CIPHER;
|
||||||
|
public const int CIPH_ECB_MODE;
|
||||||
|
public const int CIPH_CBC_MODE;
|
||||||
|
public const int CIPH_CFB_MODE;
|
||||||
|
public const int CIPH_OFB_MODE;
|
||||||
|
public const int CIPH_CTR_MODE;
|
||||||
|
public const int CIPH_GCM_MODE;
|
||||||
|
public const int CIPH_CCM_MODE;
|
||||||
|
public const int CIPH_XTS_MODE;
|
||||||
|
public const int CIPH_WRAP_MODE;
|
||||||
|
public const int CIPH_OCB_MODE;
|
||||||
|
public const int CIPH_MODE;
|
||||||
|
public const int CIPH_VARIABLE_LENGTH;
|
||||||
|
public const int CIPH_CUSTOM_IV;
|
||||||
|
public const int CIPH_ALWAYS_CALL_INIT;
|
||||||
|
public const int CIPH_CTRL_INIT;
|
||||||
|
public const int CIPH_CUSTOM_KEY_LENGTH;
|
||||||
|
public const int CIPH_NO_PADDING;
|
||||||
|
public const int CIPH_RAND_KEY;
|
||||||
|
public const int CIPH_CUSTOM_COPY;
|
||||||
|
public const int CIPH_CUSTOM_IV_LENGTH;
|
||||||
|
public const int CIPH_FLAG_DEFAULT_ASN1;
|
||||||
|
public const int CIPH_FLAG_LENGTH_BITS;
|
||||||
|
public const int CIPH_FLAG_FIPS;
|
||||||
|
public const int CIPH_FLAG_NON_FIPS_ALLOW;
|
||||||
|
public const int CIPH_FLAG_CUSTOM_CIPHER;
|
||||||
|
public const int CIPH_FLAG_AEAD_CIPHER;
|
||||||
|
public const int CIPH_FLAG_TLS1_1_MULTIBLOCK;
|
||||||
|
public const int CIPH_FLAG_PIPELINE;
|
||||||
|
|
||||||
|
public const int CTRL_INIT;
|
||||||
|
public const int CTRL_SET_KEY_LENGTH;
|
||||||
|
public const int CTRL_GET_RC2_KEY_BITS;
|
||||||
|
public const int CTRL_SET_RC2_KEY_BITS;
|
||||||
|
public const int CTRL_GET_RC5_ROUNDS;
|
||||||
|
public const int CTRL_SET_RC5_ROUNDS;
|
||||||
|
public const int CTRL_RAND_KEY;
|
||||||
|
public const int CTRL_PBE_PRF_NID;
|
||||||
|
public const int CTRL_COPY;
|
||||||
|
public const int CTRL_AEAD_SET_IVLEN;
|
||||||
|
public const int CTRL_AEAD_GET_TAG;
|
||||||
|
public const int CTRL_AEAD_SET_TAG;
|
||||||
|
public const int CTRL_AEAD_SET_IV_FIXED;
|
||||||
|
public const int CTRL_GCM_SET_IVLEN;
|
||||||
|
public const int CTRL_GCM_GET_TAG;
|
||||||
|
public const int CTRL_GCM_SET_TAG;
|
||||||
|
public const int CTRL_GCM_SET_IV_FIXED;
|
||||||
|
public const int CTRL_GCM_IV_GEN;
|
||||||
|
public const int CTRL_CCM_SET_IVLEN;
|
||||||
|
public const int CTRL_CCM_GET_TAG;
|
||||||
|
public const int CTRL_CCM_SET_TAG;
|
||||||
|
public const int CTRL_CCM_SET_IV_FIXED;
|
||||||
|
public const int CTRL_CCM_SET_L;
|
||||||
|
public const int CTRL_CCM_SET_MSGLEN;
|
||||||
|
public const int CTRL_AEAD_TLS1_AAD;
|
||||||
|
public const int CTRL_AEAD_SET_MAC_KEY;
|
||||||
|
public const int CTRL_GCM_SET_IV_INV;
|
||||||
|
public const int CTRL_TLS1_1_MULTIBLOCK_AAD;
|
||||||
|
public const int CTRL_TLS1_1_MULTIBLOCK_ENCRYPT;
|
||||||
|
public const int CTRL_TLS1_1_MULTIBLOCK_DECRYPT;
|
||||||
|
public const int CTRL_TLS1_1_MULTIBLOCK_MAX_BUFSIZE;
|
||||||
|
public const int CTRL_SSL3_MASTER_SECRET;
|
||||||
|
public const int CTRL_SET_SBOX;
|
||||||
|
public const int CTRL_SBOX_USED;
|
||||||
|
public const int CTRL_KEY_MESH;
|
||||||
|
public const int CTRL_BLOCK_PADDING_MODE;
|
||||||
|
public const int CTRL_SET_PIPELINE_OUTPUT_BUFS;
|
||||||
|
public const int CTRL_SET_PIPELINE_INPUT_BUFS;
|
||||||
|
public const int CTRL_SET_PIPELINE_INPUT_LENS;
|
||||||
|
public const int CTRL_GET_IVLEN;
|
||||||
|
|
||||||
|
[CCode (cprefix = "EVP_PADDING_")]
|
||||||
|
public enum Padding {
|
||||||
|
PKCS7,
|
||||||
|
ISO7816_4,
|
||||||
|
ANSI923,
|
||||||
|
ISO10126,
|
||||||
|
ZERO,
|
||||||
|
}
|
||||||
|
|
||||||
|
[CCode (cprefix = "EVP_PKEY_OP_")]
|
||||||
|
public enum PublicKeyOperation {
|
||||||
|
UNDEFINED,
|
||||||
|
PARAMGEN,
|
||||||
|
KEYGEN,
|
||||||
|
SIGN,
|
||||||
|
VERIFY,
|
||||||
|
VERIFYRECOVER,
|
||||||
|
SIGNCTX,
|
||||||
|
VERIFYCTX,
|
||||||
|
ENCRYPT,
|
||||||
|
DECRYPT,
|
||||||
|
DERIVE,
|
||||||
|
}
|
||||||
|
public const int PKEY_OP_TYPE_SIG;
|
||||||
|
public const int PKEY_OP_TYPE_CRYPT;
|
||||||
|
public const int PKEY_OP_TYPE_NOGEN;
|
||||||
|
public const int PKEY_OP_TYPE_GEN;
|
||||||
|
|
||||||
|
[CCode (cprefix = "EVP_PKEY_CTRL_")]
|
||||||
|
public enum PublicKeyControl {
|
||||||
|
MD,
|
||||||
|
PEER_KEY,
|
||||||
|
PKCS7_ENCRYPT,
|
||||||
|
PKCS7_DECRYPT,
|
||||||
|
PKCS7_SIGN,
|
||||||
|
SET_MAC_KEY,
|
||||||
|
DIGESTINIT,
|
||||||
|
SET_IV,
|
||||||
|
CMS_ENCRYPT,
|
||||||
|
CMS_DECRYPT,
|
||||||
|
CMS_SIGN,
|
||||||
|
CIPHER,
|
||||||
|
GET_MD,
|
||||||
|
SET_DIGEST_SIZE,
|
||||||
|
}
|
||||||
|
|
||||||
|
[CCode (cprefix = "EVP_PKEY_CTRL_", cheader_filename = "openssl/rsa.h")]
|
||||||
|
public enum PublicKeyRsaControl {
|
||||||
|
RSA_PADDING,
|
||||||
|
RSA_PSS_SALTLEN,
|
||||||
|
RSA_KEYGEN_BITS,
|
||||||
|
RSA_KEYGEN_PUBEXP,
|
||||||
|
RSA_MGF1_MD,
|
||||||
|
GET_RSA_PADDING,
|
||||||
|
GET_RSA_PSS_SALTLEN,
|
||||||
|
GET_RSA_MGF1_MD,
|
||||||
|
RSA_OAEP_MD,
|
||||||
|
RSA_OAEP_LABEL,
|
||||||
|
GET_RSA_OAEP_MD,
|
||||||
|
GET_RSA_OAEP_LABEL,
|
||||||
|
RSA_KEYGEN_PRIMES,
|
||||||
|
}
|
||||||
|
|
||||||
|
[Compact]
|
||||||
|
[CCode (cname = "EVP_PKEY", lower_case_cprefix = "EVP_PKEY_", cprefix = "EVP_PKEY_", free_function = "EVP_PKEY_free")]
|
||||||
|
public class PublicKey {
|
||||||
|
public const int NONE;
|
||||||
|
public const int RSA;
|
||||||
|
public const int RSA2;
|
||||||
|
public const int RSA_PSS;
|
||||||
|
public const int DSA;
|
||||||
|
public const int DSA1;
|
||||||
|
public const int DSA2;
|
||||||
|
public const int DSA3;
|
||||||
|
public const int DSA4;
|
||||||
|
public const int DH;
|
||||||
|
public const int DHX;
|
||||||
|
public const int EC;
|
||||||
|
public const int SM2;
|
||||||
|
public const int HMAC;
|
||||||
|
public const int CMAC;
|
||||||
|
public const int SCRYPT;
|
||||||
|
public const int TLS1_PRF;
|
||||||
|
public const int HKDF;
|
||||||
|
public const int POLY1305;
|
||||||
|
public const int SIPHASH;
|
||||||
|
public const int X25519;
|
||||||
|
public const int ED25519;
|
||||||
|
public const int X448;
|
||||||
|
public const int ED448;
|
||||||
|
|
||||||
|
public PublicKey ();
|
||||||
|
|
||||||
|
[CCode (cname = "EVP_PKEY_new_raw_private_key")]
|
||||||
|
public PublicKey.raw_private_key (int type, Engine? e, uint8[] key);
|
||||||
|
|
||||||
|
[CCode (cname = "EVP_PKEY_new_raw_public_key")]
|
||||||
|
public PublicKey.raw_public_key (int type, Engine? e, uint8[] key);
|
||||||
|
|
||||||
|
[CCode (cname = "EVP_PKEY_new_CMAC_key")]
|
||||||
|
public PublicKey.CMAC_key (Engine? e, uint8[] priv, Cipher? cipher);
|
||||||
|
|
||||||
|
[CCode (cname = "EVP_PKEY_new_mac_key")]
|
||||||
|
public PublicKey.mac_key (int type, Engine? e, uint8[] key);
|
||||||
|
|
||||||
|
public int id ();
|
||||||
|
public int size ();
|
||||||
|
public int base_id ();
|
||||||
|
public static int type (int type);
|
||||||
|
public int set_alias_type (int type);
|
||||||
|
public int up_ref ();
|
||||||
|
public RSA? get1_RSA ();
|
||||||
|
public RSA? get0_RSA ();
|
||||||
|
public int set1_RSA (RSA? key);
|
||||||
|
public int assign_RSA (RSA? key);
|
||||||
|
public int security_bits ();
|
||||||
|
|
||||||
|
[CCode (instance_pos = 1.1)]
|
||||||
|
public int print_public (BIO out, int indent, ASN1_PCTX? pctx);
|
||||||
|
|
||||||
|
[CCode (instance_pos = 1.1)]
|
||||||
|
public int print_private (BIO out, int indent, ASN1_PCTX? pctx);
|
||||||
|
|
||||||
|
public Engine? get0_engine ();
|
||||||
|
public int set1_engine (Engine? engine);
|
||||||
|
|
||||||
|
public int get_raw_private_key ([CCode (array_length = false)] uint8[] priv, out size_t len);
|
||||||
|
public int get_raw_public_key ([CCode (array_length = false)] uint8[] pub, out size_t len);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Compact]
|
||||||
|
[CCode (cname = "EVP_PKEY_CTX", lower_case_cprefix = "EVP_PKEY_CTX_", cprefix = "EVP_PKEY_CTX_", free_function = "EVP_PKEY_CTX_free")]
|
||||||
|
public class PublicKeyContext {
|
||||||
|
public PublicKeyContext (PublicKey pkey, Engine? e);
|
||||||
|
public PublicKeyContext.id (int id, Engine? e);
|
||||||
|
|
||||||
|
public PublicKeyContext dup ();
|
||||||
|
|
||||||
|
public int ctrl_str (string type, string value);
|
||||||
|
public int ctrl_uint64(int keytype, int optype, int cmd, uint64 value);
|
||||||
|
public int ctrl (int keytype, int optype, int cmd, int p1, [CCode (array_length = false)] uint8[] p2);
|
||||||
|
|
||||||
|
[CCode (cname = "EVP_PKEY_CTX_set_rsa_padding", cheader_filename = "openssl/rsa.h")]
|
||||||
|
public int set_rsa_padding (int pad);
|
||||||
|
[CCode (cname = "EVP_PKEY_CTX_get_rsa_padding", cheader_filename = "openssl/rsa.h")]
|
||||||
|
public int get_rsa_padding (out int pad);
|
||||||
|
[CCode (cname = "EVP_PKEY_CTX_set_rsa_pss_saltlen", cheader_filename = "openssl/rsa.h")]
|
||||||
|
public int set_rsa_pss_saltlen (int len);
|
||||||
|
[CCode (cname = "EVP_PKEY_CTX_get_rsa_pss_saltlen", cheader_filename = "openssl/rsa.h")]
|
||||||
|
public int get_rsa_pss_saltlen (out int len);
|
||||||
|
[CCode (cname = "EVP_PKEY_CTX_set_rsa_keygen_bits", cheader_filename = "openssl/rsa.h")]
|
||||||
|
public int set_rsa_keygen_bits (int mbits);
|
||||||
|
[CCode (cname = "EVP_PKEY_CTX_set_rsa_keygen_pubexp", cheader_filename = "openssl/rsa.h")]
|
||||||
|
public int set_rsa_keygen_pubexp (BIGNUM pubexp);
|
||||||
|
[CCode (cname = "EVP_PKEY_CTX_set_rsa_keygen_primes", cheader_filename = "openssl/rsa.h")]
|
||||||
|
public int set_rsa_keygen_primes (int primes);
|
||||||
|
|
||||||
|
public int md (int optype, int cmd, string md);
|
||||||
|
public int set_signature_md (MessageDigest md);
|
||||||
|
public int get_signature_md (out MessageDigest pmd);
|
||||||
|
public int set_mac_key (uint8[] key);
|
||||||
|
|
||||||
|
[CCode (cname = "EVP_PKEY_keygen_init")]
|
||||||
|
public int keygen_init ();
|
||||||
|
|
||||||
|
[CCode (cname = "EVP_PKEY_keygen")]
|
||||||
|
public int keygen (out PublicKey ppkey);
|
||||||
|
|
||||||
|
[CCode (cname = "EVP_PKEY_paramgen_init")]
|
||||||
|
public int paramgen_init ();
|
||||||
|
|
||||||
|
[CCode (cname = "EVP_PKEY_paramgen")]
|
||||||
|
public int paramgen (out PublicKey ppkey);
|
||||||
|
|
||||||
|
[CCode (cname = "EVP_PKEY_encrypt_init")]
|
||||||
|
public int encrypt_init ();
|
||||||
|
|
||||||
|
[CCode (cname = "EVP_PKEY_encrypt")]
|
||||||
|
public int encrypt ([CCode (array_length = false)] uint8[] out, out size_t outlen, uint8[] in);
|
||||||
|
|
||||||
|
[CCode (cname = "EVP_PKEY_decrypt_init")]
|
||||||
|
public int decrypt_init ();
|
||||||
|
|
||||||
|
[CCode (cname = "EVP_PKEY_decrypt")]
|
||||||
|
public int decrypt ([CCode (array_length = false)] uint8[] out, out size_t outlen, uint8[] in);
|
||||||
|
|
||||||
|
[CCode (cname = "EVP_PKEY_derive_init")]
|
||||||
|
public int derive_init ();
|
||||||
|
|
||||||
|
[CCode (cname = "EVP_PKEY_derive_set_peer")]
|
||||||
|
public int derive_set_peer (PublicKey peer);
|
||||||
|
|
||||||
|
[CCode (cname = "EVP_PKEY_derive")]
|
||||||
|
public int derive ([CCode (array_length = false)] uint8[] key, out size_t keylen);
|
||||||
|
|
||||||
|
[CCode (cname = "EVP_PKEY_sign_init")]
|
||||||
|
public int sign_init ();
|
||||||
|
|
||||||
|
[CCode (cname = "EVP_PKEY_sign")]
|
||||||
|
public int sign ([CCode (array_length = false)] uint8[] sig, out size_t siglen, uint8[] tbs);
|
||||||
|
|
||||||
|
[CCode (cname = "EVP_PKEY_verify_init")]
|
||||||
|
public int verify_init ();
|
||||||
|
|
||||||
|
[CCode (cname = "EVP_PKEY_verify")]
|
||||||
|
public int verify (uint8[] sig, uint8[] tbs);
|
||||||
|
|
||||||
|
[CCode (cname = "EVP_PKEY_verify_recover_init")]
|
||||||
|
public int verify_recover_init ();
|
||||||
|
|
||||||
|
[CCode (cname = "EVP_PKEY_verify_recover")]
|
||||||
|
public int verify_recover ([CCode (array_length = false)] uint8[] rout, out size_t routlen, uint8[] sig);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Compact]
|
||||||
|
[CCode (cname = "EVP_MD")]
|
||||||
|
public class MessageDigest
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public unowned MessageDigest? md_null ();
|
||||||
|
public unowned MessageDigest? md2 ();
|
||||||
|
public unowned MessageDigest? md4 ();
|
||||||
|
public unowned MessageDigest? md5 ();
|
||||||
|
public unowned MessageDigest? md5_sha1 ();
|
||||||
|
public unowned MessageDigest? blake2b512 ();
|
||||||
|
public unowned MessageDigest? blake2s256 ();
|
||||||
|
public unowned MessageDigest? sha1 ();
|
||||||
|
public unowned MessageDigest? sha224 ();
|
||||||
|
public unowned MessageDigest? sha256 ();
|
||||||
|
public unowned MessageDigest? sha384 ();
|
||||||
|
public unowned MessageDigest? sha512 ();
|
||||||
|
public unowned MessageDigest? mdc2 ();
|
||||||
|
public unowned MessageDigest? ripmed160 ();
|
||||||
|
public unowned MessageDigest? whirlpool ();
|
||||||
|
[CCode (cname = "get_digestbyname")]
|
||||||
|
public unowned MessageDigest? get_digest_by_name (string name);
|
||||||
|
|
||||||
|
[Compact]
|
||||||
|
[CCode (cname = "EVP_MD_CTX", lower_case_cprefix = "EVP_MD_CTX_")]
|
||||||
|
public class MessageDigestContext
|
||||||
|
{
|
||||||
|
public MessageDigestContext ();
|
||||||
|
[CCode (cname = "EVP_DigestInit_ex")]
|
||||||
|
public int init (MessageDigest type, Engine? engine);
|
||||||
|
[CCode (cname = "EVP_DigestUpdate")]
|
||||||
|
public int update (uint8[] d);
|
||||||
|
[CCode (cname = "EVP_DigestFinal_ex")]
|
||||||
|
public int final ([CCode (array_length = false)] uchar[] md, out int s);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Compact]
|
||||||
|
[CCode (cname = "EVP_CIPHER", lower_case_cprefix = "EVP_CIPHER_")]
|
||||||
|
public class Cipher
|
||||||
|
{
|
||||||
|
[CCode (cname = "EVP_CIPHER_meth_new")]
|
||||||
|
public Cipher (int cipher_type, int block_size, int key_len);
|
||||||
|
public int key_length ();
|
||||||
|
public int iv_length ();
|
||||||
|
}
|
||||||
|
|
||||||
|
public unowned Cipher? enc_null ();
|
||||||
|
public unowned Cipher? des_ecb ();
|
||||||
|
public unowned Cipher? des_ede ();
|
||||||
|
public unowned Cipher? des_ede3 ();
|
||||||
|
public unowned Cipher? des_ede_ecb ();
|
||||||
|
public unowned Cipher? des_ede3_ecb ();
|
||||||
|
public unowned Cipher? des_cfb64 ();
|
||||||
|
public unowned Cipher? des_cfb1 ();
|
||||||
|
public unowned Cipher? des_cfb8 ();
|
||||||
|
public unowned Cipher? des_ede_cfb64 ();
|
||||||
|
public unowned Cipher? des_ede3_cfb64 ();
|
||||||
|
public unowned Cipher? des_ede3_cfb1 ();
|
||||||
|
public unowned Cipher? des_ede3_cfb8 ();
|
||||||
|
public unowned Cipher? des_ofb ();
|
||||||
|
public unowned Cipher? des_ede_ofb ();
|
||||||
|
public unowned Cipher? des_ede3_ofb ();
|
||||||
|
public unowned Cipher? des_cbc ();
|
||||||
|
public unowned Cipher? des_ede_cbc ();
|
||||||
|
public unowned Cipher? des_ede3_cbc ();
|
||||||
|
public unowned Cipher? desx_cbc ();
|
||||||
|
public unowned Cipher? des_ede3_wrap ();
|
||||||
|
public unowned Cipher? rc4 ();
|
||||||
|
public unowned Cipher? rc4_40 ();
|
||||||
|
public unowned Cipher? rc4_hmac_md5 ();
|
||||||
|
public unowned Cipher? idea_ecb ();
|
||||||
|
public unowned Cipher? idea_cfb64 ();
|
||||||
|
public unowned Cipher? idea_ofb ();
|
||||||
|
public unowned Cipher? idea_cbc ();
|
||||||
|
public unowned Cipher? rc2_ecb ();
|
||||||
|
public unowned Cipher? rc2_cbc ();
|
||||||
|
public unowned Cipher? rc2_40_cbc ();
|
||||||
|
public unowned Cipher? rc2_64_cbc ();
|
||||||
|
public unowned Cipher? rc2_cfb64 ();
|
||||||
|
public unowned Cipher? rc2_ofb ();
|
||||||
|
public unowned Cipher? bf_ecb ();
|
||||||
|
public unowned Cipher? bf_cbc ();
|
||||||
|
public unowned Cipher? bf_cfb64 ();
|
||||||
|
public unowned Cipher? bf_ofb ();
|
||||||
|
public unowned Cipher? cast5_ecb ();
|
||||||
|
public unowned Cipher? cast5_cbc ();
|
||||||
|
public unowned Cipher? cast5_cfb64 ();
|
||||||
|
public unowned Cipher? cast5_ofb ();
|
||||||
|
public unowned Cipher? rc5_32_12_16_cbc ();
|
||||||
|
public unowned Cipher? rc5_32_12_16_ecb ();
|
||||||
|
public unowned Cipher? rc5_32_12_16_cfb64 ();
|
||||||
|
public unowned Cipher? rc5_32_12_16_ofb ();
|
||||||
|
public unowned Cipher? aes_128_ecb ();
|
||||||
|
public unowned Cipher? aes_128_cbc ();
|
||||||
|
public unowned Cipher? aes_128_cfb1 ();
|
||||||
|
public unowned Cipher? aes_128_cfb8 ();
|
||||||
|
public unowned Cipher? aes_128_cfb128 ();
|
||||||
|
public unowned Cipher? aes_128_ofb ();
|
||||||
|
public unowned Cipher? aes_128_ctr ();
|
||||||
|
public unowned Cipher? aes_128_ccm ();
|
||||||
|
public unowned Cipher? aes_128_gcm ();
|
||||||
|
public unowned Cipher? aes_128_xts ();
|
||||||
|
public unowned Cipher? aes_128_wrap ();
|
||||||
|
public unowned Cipher? aes_128_wrap_pad ();
|
||||||
|
public unowned Cipher? aes_128_ocb ();
|
||||||
|
public unowned Cipher? aes_192_ecb ();
|
||||||
|
public unowned Cipher? aes_192_cbc ();
|
||||||
|
public unowned Cipher? aes_192_cfb1 ();
|
||||||
|
public unowned Cipher? aes_192_cfb8 ();
|
||||||
|
public unowned Cipher? aes_192_cfb128 ();
|
||||||
|
public unowned Cipher? aes_192_ofb ();
|
||||||
|
public unowned Cipher? aes_192_ctr ();
|
||||||
|
public unowned Cipher? aes_192_ccm ();
|
||||||
|
public unowned Cipher? aes_192_gcm ();
|
||||||
|
public unowned Cipher? aes_192_wrap ();
|
||||||
|
public unowned Cipher? aes_192_wrap_pad ();
|
||||||
|
public unowned Cipher? aes_192_ocb ();
|
||||||
|
public unowned Cipher? aes_256_ecb ();
|
||||||
|
public unowned Cipher? aes_256_cbc ();
|
||||||
|
public unowned Cipher? aes_256_cfb1 ();
|
||||||
|
public unowned Cipher? aes_256_cfb8 ();
|
||||||
|
public unowned Cipher? aes_256_cfb128 ();
|
||||||
|
public unowned Cipher? aes_256_ofb ();
|
||||||
|
public unowned Cipher? aes_256_ctr ();
|
||||||
|
public unowned Cipher? aes_256_ccm ();
|
||||||
|
public unowned Cipher? aes_256_gcm ();
|
||||||
|
public unowned Cipher? aes_256_xts ();
|
||||||
|
public unowned Cipher? aes_256_wrap ();
|
||||||
|
public unowned Cipher? aes_256_wrap_pad ();
|
||||||
|
public unowned Cipher? aes_256_ocb ();
|
||||||
|
public unowned Cipher? aes_128_cbc_hmac_sha1 ();
|
||||||
|
public unowned Cipher? aes_256_cbc_hmac_sha1 ();
|
||||||
|
public unowned Cipher? aes_128_cbc_hmac_sha256 ();
|
||||||
|
public unowned Cipher? aes_256_cbc_hmac_sha256 ();
|
||||||
|
public unowned Cipher? camellia_128_ecb ();
|
||||||
|
public unowned Cipher? camellia_128_cbc ();
|
||||||
|
public unowned Cipher? camellia_128_cfb1 ();
|
||||||
|
public unowned Cipher? camellia_128_cfb8 ();
|
||||||
|
public unowned Cipher? camellia_128_cfb128 ();
|
||||||
|
public unowned Cipher? camellia_128_ofb ();
|
||||||
|
public unowned Cipher? camellia_128_ctr ();
|
||||||
|
public unowned Cipher? camellia_192_ecb ();
|
||||||
|
public unowned Cipher? camellia_192_cbc ();
|
||||||
|
public unowned Cipher? camellia_192_cfb1 ();
|
||||||
|
public unowned Cipher? camellia_192_cfb8 ();
|
||||||
|
public unowned Cipher? camellia_192_cfb128 ();
|
||||||
|
public unowned Cipher? camellia_192_ofb ();
|
||||||
|
public unowned Cipher? camellia_192_ctr ();
|
||||||
|
public unowned Cipher? camellia_256_ecb ();
|
||||||
|
public unowned Cipher? camellia_256_cbc ();
|
||||||
|
public unowned Cipher? camellia_256_cfb1 ();
|
||||||
|
public unowned Cipher? camellia_256_cfb8 ();
|
||||||
|
public unowned Cipher? camellia_256_cfb128 ();
|
||||||
|
public unowned Cipher? camellia_256_ofb ();
|
||||||
|
public unowned Cipher? camellia_256_ctr ();
|
||||||
|
public unowned Cipher? chacha20 ();
|
||||||
|
public unowned Cipher? chacha20_poly1305 ();
|
||||||
|
public unowned Cipher? seed_ecb ();
|
||||||
|
public unowned Cipher? seed_cbc ();
|
||||||
|
public unowned Cipher? seed_cfb128 ();
|
||||||
|
public unowned Cipher? seed_ofb ();
|
||||||
|
[CCode (cname = "EVP_get_cipherbyname")]
|
||||||
|
public unowned Cipher? get_cipher_by_name (string name);
|
||||||
|
|
||||||
|
[CCode (cname = "EVP_BytesToKey")]
|
||||||
|
public int bytes_to_key (Cipher cipher, MessageDigest md, [CCode (array_length = false)] uchar[] salt, uchar[] key_data, int nrounds, [CCode (array_length = false)] uchar[] key, [CCode (array_length = false)] uchar[] iv);
|
||||||
|
|
||||||
|
[Compact]
|
||||||
|
[CCode (cname = "EVP_CIPHER_CTX", cprefix = "EVP_CIPHER_CTX_", lower_case_cprefix = "EVP_CIPHER_CTX_")]
|
||||||
|
public class CipherContext
|
||||||
|
{
|
||||||
|
public CipherContext ();
|
||||||
|
|
||||||
|
public int reset ();
|
||||||
|
|
||||||
|
public int set_key_length (int keylen);
|
||||||
|
public int set_padding (int pad);
|
||||||
|
|
||||||
|
[CCode (cname = "EVP_EncryptInit_ex")]
|
||||||
|
public int encrypt_init (Cipher? cipher, Engine? engine, [CCode (array_length = false)] uchar[]? key, [CCode (array_length = false)] uchar[]? iv);
|
||||||
|
|
||||||
|
[CCode (cname = "EVP_EncryptUpdate")]
|
||||||
|
public int encrypt_update ([CCode (array_length = false)] uchar[] ciphertext, out int ciphertext_len, uchar[] plaintext);
|
||||||
|
|
||||||
|
[CCode (cname = "EVP_EncryptFinal_ex")]
|
||||||
|
public int encrypt_final ([CCode (array_length = false)] uchar[] ciphertext, out int ciphertext_len);
|
||||||
|
|
||||||
|
[CCode (cname = "EVP_DecryptInit_ex")]
|
||||||
|
public int decrypt_init (Cipher? cipher, Engine? engine, [CCode (array_length = false)] uchar[]? key, [CCode (array_length = false)] uchar[]? iv);
|
||||||
|
|
||||||
|
[CCode (cname = "EVP_DecryptUpdate")]
|
||||||
|
public int decrypt_update ([CCode (array_length = false)] uchar[] plaintext, out int plaintext_len, uchar[] ciphertext);
|
||||||
|
|
||||||
|
[CCode (cname = "EVP_DecryptFinal_ex")]
|
||||||
|
public int decrypt_final ([CCode (array_length = false)] uchar[] plaintext, out int plaintext_len);
|
||||||
|
|
||||||
|
[CCode (simple_generics = true)]
|
||||||
|
public int ctrl<T>(int type, int arg, T? ptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Compact]
|
||||||
|
[CCode (cname = "BIGNUM", cheader_filename = "openssl/rsa.h", free_function = "BN_free")]
|
||||||
|
public class BIGNUM {
|
||||||
|
[CCode (cname = "BN_new", cheader_filename = "openssl/bn.h")]
|
||||||
|
public BIGNUM ();
|
||||||
|
|
||||||
|
[CCode (cname = "BN_secure_new", cheader_filename = "openssl/bn.h")]
|
||||||
|
public BIGNUM.secure ();
|
||||||
|
|
||||||
|
[CCode (cname = "BN_clear", cheader_filename = "openssl/bn.h")]
|
||||||
|
public void clear ();
|
||||||
|
|
||||||
|
[CCode (cname = "BN_set_word", cheader_filename = "openssl/bn.h")]
|
||||||
|
public int set_word (ulong w);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Compact]
|
||||||
|
[CCode (cname = "BN_GENCB", cheader_filename = "openssl/rsa.h", free_function = "BN_GENCB_free")]
|
||||||
|
public class BN_GENCB {
|
||||||
|
public delegate int BigNumGenCallback (int a, int b, BN_GENCB gcb);
|
||||||
|
|
||||||
|
[CCode (cname = "BN_GENCB_new")]
|
||||||
|
public BN_GENCB ();
|
||||||
|
|
||||||
|
[CCode (cname = "BN_GENCB_set")]
|
||||||
|
public void set (BigNumGenCallback cb, [CCode (array_length = false)] uint8[] cb_arg);
|
||||||
|
|
||||||
|
[CCode (cname = "BN_GENCB_call")]
|
||||||
|
public int call (int a, int b);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Compact]
|
||||||
|
[CCode (lower_case_cprefix = "RSA_", cprefix = "RSA_", cheader_filename = "openssl/rsa.h", free_function = "RSA_free")]
|
||||||
|
public class RSA
|
||||||
|
{
|
||||||
|
public const int PKCS1_PADDING;
|
||||||
|
public const int SSLV23_PADDING;
|
||||||
|
public const int NO_PADDING;
|
||||||
|
public const int PKCS1_OAEP_PADDING;
|
||||||
|
public const int X931_PADDING;
|
||||||
|
public const int PKCS1_PSS_PADDING;
|
||||||
|
public const int F4;
|
||||||
|
[CCode (cname = "RSA_3")]
|
||||||
|
public const int RSA_3;
|
||||||
|
|
||||||
|
public RSA ();
|
||||||
|
|
||||||
|
public int size ();
|
||||||
|
|
||||||
|
public int set0_key (BIGNUM n, BIGNUM e, BIGNUM d);
|
||||||
|
public void get0_key (out BIGNUM n, out BIGNUM e, out BIGNUM d);
|
||||||
|
|
||||||
|
public void clear_flags (int flags);
|
||||||
|
public int test_flags (int flags);
|
||||||
|
public void set_flags (int flags);
|
||||||
|
public Engine get0_engine ();
|
||||||
|
|
||||||
|
[CCode (instance_pos = 1.1)]
|
||||||
|
public int print_fp (GLib.FileStream fp, int offset);
|
||||||
|
[CCode (instance_pos = 1.1)]
|
||||||
|
public int print (BIO bp, int offset);
|
||||||
|
public int generate_key_ex (int bits, BIGNUM e, BN_GENCB? cb = null);
|
||||||
|
[CCode (instance_pos = 4)]
|
||||||
|
public bool sign (int type, uint8[] m, [CCode (array_length = false)] uint8[] sigret, out int siglen);
|
||||||
|
[CCode (instance_pos = 3)]
|
||||||
|
public int verify (int type, uint8[] m, uint8[] sigbuf);
|
||||||
|
[CCode (instance_pos = 2.1)]
|
||||||
|
public int public_encrypt ([CCode (array_length_pos = 0)] uint8[] from, [CCode (array_length = false)] uint8[] to, int padding);
|
||||||
|
[CCode (instance_pos = 2.1)]
|
||||||
|
public int private_encrypt ([CCode (array_length_pos = 0)] uint8[] from, [CCode (array_length = false)] uint8[] to, int padding);
|
||||||
|
[CCode (instance_pos = 2.1)]
|
||||||
|
public int public_decrypt ([CCode (array_length_pos = 0)] uint8[] from, [CCode (array_length = false)] uint8[] to,int padding);
|
||||||
|
[CCode (instance_pos = 2.1)]
|
||||||
|
public int private_decrypt ([CCode (array_length_pos = 0)] uint8[] from, [CCode (array_length = false)] uint8[] to, int padding);
|
||||||
|
}
|
||||||
|
|
||||||
|
[CCode (lower_case_cprefix = "PEM_", cheader_filename = "openssl/pem.h")]
|
||||||
|
namespace PEM
|
||||||
|
{
|
||||||
|
[CCode (cname = "pem_password_cb")]
|
||||||
|
public delegate int PasswordCallback (uint8[] buf, int flag);
|
||||||
|
public void read_RSAPrivateKey (GLib.FileStream f, out RSA x, PasswordCallback? cb = null);
|
||||||
|
public void read_RSAPublicKey (GLib.FileStream f, out RSA x, PasswordCallback? cb = null);
|
||||||
|
public int write_RSAPrivateKey (GLib.FileStream f, RSA x, EVP.Cipher? enc, uint8[] kstr, PasswordCallback? cb = null);
|
||||||
|
public int write_RSAPublicKey (GLib.FileStream f, RSA x);
|
||||||
|
|
||||||
|
public void read_bio_RSAPublicKey (BIO bp, out RSA x, PasswordCallback? cb = null);
|
||||||
|
public void read_bio_RSAPrivateKey (BIO bp, out RSA x, PasswordCallback? cb = null);
|
||||||
|
public bool write_bio_RSAPublicKey (BIO bp, RSA x);
|
||||||
|
public bool write_bio_RSAPrivateKey (BIO bp, RSA x, EVP.Cipher? enc, uint8[] kstr, PasswordCallback? cb = null);
|
||||||
|
|
||||||
|
public void read_bio_PUBKEY (BIO bp, out EVP.PublicKey x, PasswordCallback? cb = null);
|
||||||
|
public int write_bio_PUBKEY (BIO bp, EVP.PublicKey x);
|
||||||
|
public void read_PUBKEY (GLib.FileStream fp, out EVP.PublicKey x, PasswordCallback? cb = null);
|
||||||
|
public int write_PUBKEY (GLib.FileStream fp, EVP.PublicKey x);
|
||||||
|
|
||||||
|
public void read_bio_PrivateKey (BIO bp, out EVP.PublicKey x, PasswordCallback? cb = null);
|
||||||
|
public void read_PrivateKey (GLib.FileStream fp, out EVP.PublicKey x, PasswordCallback? cb = null);
|
||||||
|
public int write_bio_PrivateKey (BIO bp, EVP.PublicKey x, EVP.Cipher? enc, uint8[] kstr, PasswordCallback? cb = null);
|
||||||
|
public int write_bio_PrivateKey_traditional (BIO bp, EVP.PublicKey x, EVP.Cipher? enc, uint8[] kstr, PasswordCallback? cb = null);
|
||||||
|
public int write_PrivateKey (GLib.FileStream fp, EVP.PublicKey x, EVP.Cipher? enc, uint8[] kstr, PasswordCallback? cb = null);
|
||||||
|
public int write_bio_PKCS8PrivateKey (BIO bp, EVP.PublicKey x, EVP.Cipher? enc, uint8[] kstr, PasswordCallback? cb = null);
|
||||||
|
public int write_bio_PKCS8PrivateKey_nid (BIO bp, EVP.PublicKey x, int nid, uint8[] kstr, PasswordCallback? cb = null);
|
||||||
|
public int write_PKCS8PrivateKey (GLib.FileStream fp, EVP.PublicKey x, EVP.Cipher? enc, uint8[] kstr, PasswordCallback? cb = null);
|
||||||
|
public int write_PKCS8PrivateKey_nid (GLib.FileStream fp, EVP.PublicKey x, int nid, uint8[] kstr, PasswordCallback? cb = null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public RSA? d2i_RSA_PUBKEY (out RSA a, uint8[] ppin);
|
||||||
|
public RSA? d2i_RSA_PUBKEY_bio (BIO bp, out RSA a);
|
||||||
|
public RSA? d2i_RSA_PUBKEY_fp (GLib.FileStream fp, out RSA a);
|
||||||
|
|
||||||
|
public int i2d_RSA_PUBKEY (RSA rsa, [CCode (array_length = false)] out uint8[] ppout);
|
||||||
|
public int i2d_RSA_PUBKEY_fp (GLib.FileStream fp, RSA a);
|
||||||
|
public int i2d_RSA_PUBKEY_bio (BIO bp, RSA a);
|
||||||
|
|
||||||
|
[CCode (cprefix = "ERR_", lower_case_cprefix = "ERR_", cheader_filename = "openssl/err.h")]
|
||||||
|
namespace ERR
|
||||||
|
{
|
||||||
|
public ulong get_error();
|
||||||
|
public unowned string? reason_error_string(ulong e);
|
||||||
|
}
|
||||||
|
|
||||||
|
[CCode (cprefix = "RAND_", lower_case_cprefix = "RAND_", cheader_filename = "openssl/rand.h")]
|
||||||
|
namespace RAND
|
||||||
|
{
|
||||||
|
public int bytes(uint8[] buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
BIN
dino_plus.png
Normal file
BIN
dino_plus.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 213 KiB |
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"id": "im.dino.Dino",
|
"id": "im.dino.Dino",
|
||||||
"runtime": "org.gnome.Platform",
|
"runtime": "org.gnome.Platform",
|
||||||
"runtime-version": "44",
|
"runtime-version": "46",
|
||||||
"sdk": "org.gnome.Sdk",
|
"sdk": "org.gnome.Sdk",
|
||||||
"command": "dino",
|
"command": "dino",
|
||||||
"finish-args": [
|
"finish-args": [
|
||||||
|
@ -16,6 +16,7 @@
|
||||||
"--talk-name=org.freedesktop.Notifications"
|
"--talk-name=org.freedesktop.Notifications"
|
||||||
],
|
],
|
||||||
"modules": [
|
"modules": [
|
||||||
|
"shared-modules/libcanberra/libcanberra.json",
|
||||||
{
|
{
|
||||||
"name": "libsignal-protocol-c",
|
"name": "libsignal-protocol-c",
|
||||||
"buildsystem": "cmake-ninja",
|
"buildsystem": "cmake-ninja",
|
||||||
|
@ -59,7 +60,11 @@
|
||||||
"buildsystem": "cmake-ninja",
|
"buildsystem": "cmake-ninja",
|
||||||
"builddir": true,
|
"builddir": true,
|
||||||
"config-opts": [
|
"config-opts": [
|
||||||
"-DSOUP_VERSION=3"
|
"-DSOUP_VERSION=3",
|
||||||
|
"-DNO_DEBUG=yes",
|
||||||
|
"-DCMAKE_BUILD_TYPE=Release",
|
||||||
|
"-DENABLED_PLUGINS=notification-sound",
|
||||||
|
"-DPLUGIN_RTP_WEBRTC_AUDIO_PROCESSING=OFF"
|
||||||
],
|
],
|
||||||
"cleanup": [
|
"cleanup": [
|
||||||
"/include",
|
"/include",
|
||||||
|
|
|
@ -102,7 +102,8 @@ DEPENDS
|
||||||
${CMAKE_BINARY_DIR}/exports/dino_i18n.h
|
${CMAKE_BINARY_DIR}/exports/dino_i18n.h
|
||||||
)
|
)
|
||||||
|
|
||||||
add_definitions(${VALA_CFLAGS} -DDINO_SYSTEM_PLUGIN_DIR="${PLUGIN_INSTALL_DIR}" -DDINO_SYSTEM_LIBDIR_NAME="${LIBDIR_NAME}" -DG_LOG_DOMAIN="libdino" -DDINO_VERSION=\"${PROJECT_VERSION}\")
|
add_definitions(${VALA_CFLAGS} -DDINO_SYSTEM_PLUGIN_DIR="${PLUGIN_INSTALL_DIR}" -DDINO_SYSTEM_LIBDIR_NAME="${LIBDIR_NAME}" -DG_LOG_DOMAIN="libdino"
|
||||||
|
-DDINO_VERSION=\"${PROJECT_VERSION}\" -DDINO_SYSTEM_LOCALEDIR_NAME="${LOCALEDIR_NAME}")
|
||||||
add_library(libdino SHARED ${LIBDINO_VALA_C} ${CMAKE_BINARY_DIR}/exports/dino_i18n.h)
|
add_library(libdino SHARED ${LIBDINO_VALA_C} ${CMAKE_BINARY_DIR}/exports/dino_i18n.h)
|
||||||
add_dependencies(libdino dino-vapi)
|
add_dependencies(libdino dino-vapi)
|
||||||
target_link_libraries(libdino xmpp-vala qlite ${LIBDINO_PACKAGES} m)
|
target_link_libraries(libdino xmpp-vala qlite ${LIBDINO_PACKAGES} m)
|
||||||
|
@ -112,12 +113,13 @@ install(TARGETS libdino ${TARGET_INSTALL})
|
||||||
install(FILES ${CMAKE_BINARY_DIR}/exports/dino.vapi ${CMAKE_BINARY_DIR}/exports/dino.deps DESTINATION ${VAPI_INSTALL_DIR})
|
install(FILES ${CMAKE_BINARY_DIR}/exports/dino.vapi ${CMAKE_BINARY_DIR}/exports/dino.deps DESTINATION ${VAPI_INSTALL_DIR})
|
||||||
install(FILES ${CMAKE_BINARY_DIR}/exports/dino.h ${CMAKE_BINARY_DIR}/exports/dino_i18n.h DESTINATION ${INCLUDE_INSTALL_DIR})
|
install(FILES ${CMAKE_BINARY_DIR}/exports/dino.h ${CMAKE_BINARY_DIR}/exports/dino_i18n.h DESTINATION ${INCLUDE_INSTALL_DIR})
|
||||||
|
|
||||||
if(BUILD_TESTS)
|
if(BUILD_TESTING)
|
||||||
vala_precompile(LIBDINO_TEST_VALA_C
|
vala_precompile(LIBDINO_TEST_VALA_C
|
||||||
SOURCES
|
SOURCES
|
||||||
"tests/weak_map.vala"
|
"tests/weak_map.vala"
|
||||||
"tests/testcase.vala"
|
"tests/testcase.vala"
|
||||||
"tests/common.vala"
|
"tests/common.vala"
|
||||||
|
"tests/jid.vala"
|
||||||
CUSTOM_VAPIS
|
CUSTOM_VAPIS
|
||||||
${CMAKE_BINARY_DIR}/exports/dino_internal.vapi
|
${CMAKE_BINARY_DIR}/exports/dino_internal.vapi
|
||||||
${CMAKE_BINARY_DIR}/exports/xmpp-vala.vapi
|
${CMAKE_BINARY_DIR}/exports/xmpp-vala.vapi
|
||||||
|
@ -131,4 +133,5 @@ if(BUILD_TESTS)
|
||||||
add_definitions(${VALA_CFLAGS})
|
add_definitions(${VALA_CFLAGS})
|
||||||
add_executable(libdino-test ${LIBDINO_TEST_VALA_C})
|
add_executable(libdino-test ${LIBDINO_TEST_VALA_C})
|
||||||
target_link_libraries(libdino-test libdino)
|
target_link_libraries(libdino-test libdino)
|
||||||
endif(BUILD_TESTS)
|
add_test(NAME libdino COMMAND libdino-test)
|
||||||
|
endif(BUILD_TESTING)
|
||||||
|
|
|
@ -79,8 +79,9 @@ sources = files(
|
||||||
)
|
)
|
||||||
sources += [version_vala]
|
sources += [version_vala]
|
||||||
c_args = [
|
c_args = [
|
||||||
'-DDINO_SYSTEM_LIBDIR_NAME="@0@"'.format(get_option('prefix') / get_option('libdir')),
|
'-DDINO_SYSTEM_LIBDIR_NAME="@0@"'.format(get_option('libdir')),
|
||||||
'-DDINO_SYSTEM_PLUGIN_DIR="@0@"'.format(get_option('prefix') / get_option('plugindir')),
|
'-DDINO_SYSTEM_LOCALEDIR_NAME="@0@"'.format(get_option('localedir')),
|
||||||
|
'-DDINO_SYSTEM_PLUGIN_DIR="@0@"'.format(get_option('prefix') / get_option('libdir') / get_option('plugindir')),
|
||||||
'-DG_LOG_DOMAIN="libdino"',
|
'-DG_LOG_DOMAIN="libdino"',
|
||||||
]
|
]
|
||||||
lib_dino = library('dino', sources, c_args: c_args, include_directories: include_directories('src'), dependencies: dependencies, version: '0.0', install: true, install_dir: [true, true, true])
|
lib_dino = library('dino', sources, c_args: c_args, include_directories: include_directories('src'), dependencies: dependencies, version: '0.0', install: true, install_dir: [true, true, true])
|
||||||
|
@ -88,3 +89,12 @@ dep_dino = declare_dependency(link_with: lib_dino, include_directories: include_
|
||||||
|
|
||||||
install_data('dino.deps', install_dir: get_option('datadir') / 'vala/vapi') # TODO: workaround for https://github.com/mesonbuild/meson/issues/9756
|
install_data('dino.deps', install_dir: get_option('datadir') / 'vala/vapi') # TODO: workaround for https://github.com/mesonbuild/meson/issues/9756
|
||||||
install_headers('src/dino_i18n.h')
|
install_headers('src/dino_i18n.h')
|
||||||
|
|
||||||
|
sources = files(
|
||||||
|
'tests/weak_map.vala',
|
||||||
|
'tests/testcase.vala',
|
||||||
|
'tests/common.vala',
|
||||||
|
'tests/jid.vala',
|
||||||
|
)
|
||||||
|
test_libdino = executable('test_libdino', sources, dependencies: dependencies + [dep_dino])
|
||||||
|
test('libdino', test_libdino)
|
||||||
|
|
|
@ -25,13 +25,13 @@ public interface Application : GLib.Application {
|
||||||
|
|
||||||
public abstract void handle_uri(string jid, string query, Gee.Map<string, string> options);
|
public abstract void handle_uri(string jid, string query, Gee.Map<string, string> options);
|
||||||
|
|
||||||
public void init() throws Error {
|
public void init(bool default_dark_theme) throws Error {
|
||||||
if (DirUtils.create_with_parents(get_storage_dir(), 0700) == -1) {
|
if (DirUtils.create_with_parents(get_storage_dir(), 0700) == -1) {
|
||||||
throw new Error(-1, 0, "Could not create storage dir \"%s\": %s", get_storage_dir(), FileUtils.error_from_errno(errno).to_string());
|
throw new Error(-1, 0, "Could not create storage dir \"%s\": %s", get_storage_dir(), FileUtils.error_from_errno(errno).to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
this.db = new Database(Path.build_filename(get_storage_dir(), "dino.db"));
|
this.db = new Database(Path.build_filename(get_storage_dir(), "dino.db"));
|
||||||
this.settings = new Dino.Entities.Settings.from_db(db);
|
this.settings = new Dino.Entities.Settings.from_db(db, default_dark_theme);
|
||||||
this.stream_interactor = new StreamInteractor(db);
|
this.stream_interactor = new StreamInteractor(db);
|
||||||
|
|
||||||
MessageProcessor.start(stream_interactor, db);
|
MessageProcessor.start(stream_interactor, db);
|
||||||
|
|
|
@ -2,6 +2,8 @@ using Xmpp;
|
||||||
|
|
||||||
namespace Dino.Entities {
|
namespace Dino.Entities {
|
||||||
|
|
||||||
|
const int HISTORY_SYNC_MAM_MESSAGES = 20;
|
||||||
|
|
||||||
public class Conversation : Object {
|
public class Conversation : Object {
|
||||||
|
|
||||||
public signal void object_updated(Conversation conversation);
|
public signal void object_updated(Conversation conversation);
|
||||||
|
@ -33,7 +35,7 @@ public class Conversation : Object {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public Encryption encryption { get; set; default = Encryption.NONE; }
|
public Encryption encryption { get; set; default = Encryption.UNKNOWN; }
|
||||||
public Message? read_up_to { get; set; }
|
public Message? read_up_to { get; set; }
|
||||||
public int read_up_to_item { get; set; default=-1; }
|
public int read_up_to_item { get; set; default=-1; }
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,27 @@ namespace Dino.Entities {
|
||||||
public bool is_some() {
|
public bool is_some() {
|
||||||
return this != NONE;
|
return this != NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Encryption parse(string str) {
|
||||||
|
switch (str) {
|
||||||
|
case "DINO_ENTITIES_ENCRYPTION_NONE":
|
||||||
|
return NONE;
|
||||||
|
case "DINO_ENTITIES_ENCRYPTION_PGP":
|
||||||
|
return PGP;
|
||||||
|
case "DINO_ENTITIES_ENCRYPTION_OMEMO":
|
||||||
|
return OMEMO;
|
||||||
|
case "DINO_ENTITIES_ENCRYPTION_DTLS_SRTP":
|
||||||
|
return DTLS_SRTP;
|
||||||
|
case "DINO_ENTITIES_ENCRYPTION_SRTP":
|
||||||
|
return SRTP;
|
||||||
|
case "DINO_ENTITIES_ENCRYPTION_UNKNOWN":
|
||||||
|
// Fall through.
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return UNKNOWN;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -71,6 +71,7 @@ public class FileTransfer : Object {
|
||||||
public int provider { get; set; }
|
public int provider { get; set; }
|
||||||
public string info { get; set; }
|
public string info { get; set; }
|
||||||
public Cancellable cancellable { get; default=new Cancellable(); }
|
public Cancellable cancellable { get; default=new Cancellable(); }
|
||||||
|
public uint64 transferred_bytes { get; set; }
|
||||||
|
|
||||||
private Database? db;
|
private Database? db;
|
||||||
private string storage_dir;
|
private string storage_dir;
|
||||||
|
|
|
@ -4,7 +4,7 @@ public class Settings : Object {
|
||||||
|
|
||||||
private Database db;
|
private Database db;
|
||||||
|
|
||||||
public Settings.from_db(Database db) {
|
public Settings.from_db(Database db, bool default_dark_theme) {
|
||||||
this.db = db;
|
this.db = db;
|
||||||
|
|
||||||
send_typing_ = col_to_bool_or_default("send_typing", true);
|
send_typing_ = col_to_bool_or_default("send_typing", true);
|
||||||
|
@ -12,6 +12,10 @@ public class Settings : Object {
|
||||||
notifications_ = col_to_bool_or_default("notifications", true);
|
notifications_ = col_to_bool_or_default("notifications", true);
|
||||||
convert_utf8_smileys_ = col_to_bool_or_default("convert_utf8_smileys", true);
|
convert_utf8_smileys_ = col_to_bool_or_default("convert_utf8_smileys", true);
|
||||||
check_spelling = col_to_bool_or_default("check_spelling", true);
|
check_spelling = col_to_bool_or_default("check_spelling", true);
|
||||||
|
default_encryption = col_to_encryption_or_default("default_encryption", Encryption.UNKNOWN);
|
||||||
|
send_button = col_to_bool_or_default("send_button", false);
|
||||||
|
enter_newline = col_to_bool_or_default("enter_newline", false);
|
||||||
|
dark_theme = col_to_bool_or_default("dark_theme", default_dark_theme);
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool col_to_bool_or_default(string key, bool def) {
|
private bool col_to_bool_or_default(string key, bool def) {
|
||||||
|
@ -19,6 +23,12 @@ public class Settings : Object {
|
||||||
return val != null ? bool.parse(val) : def;
|
return val != null ? bool.parse(val) : def;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Encryption col_to_encryption_or_default(string key, Encryption def) {
|
||||||
|
var sval = db.settings.value;
|
||||||
|
string? val = db.settings.select({sval}).with(db.settings.key, "=", key)[sval];
|
||||||
|
return val != null ? Encryption.parse(val) : def;
|
||||||
|
}
|
||||||
|
|
||||||
private bool send_typing_;
|
private bool send_typing_;
|
||||||
public bool send_typing {
|
public bool send_typing {
|
||||||
get { return send_typing_; }
|
get { return send_typing_; }
|
||||||
|
@ -79,6 +89,60 @@ public class Settings : Object {
|
||||||
check_spelling_ = value;
|
check_spelling_ = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Encryption default_encryption_;
|
||||||
|
public Encryption default_encryption {
|
||||||
|
get { return default_encryption_; }
|
||||||
|
set {
|
||||||
|
string valstr = value.to_string();
|
||||||
|
db.settings.upsert()
|
||||||
|
.value(db.settings.key, "default_encryption", true)
|
||||||
|
.value(db.settings.value, valstr)
|
||||||
|
.perform();
|
||||||
|
default_encryption_ = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public signal void send_button_update(bool visible);
|
||||||
|
private bool send_button_;
|
||||||
|
public bool send_button {
|
||||||
|
get { return send_button_; }
|
||||||
|
set {
|
||||||
|
db.settings.upsert()
|
||||||
|
.value(db.settings.key, "send_button", true)
|
||||||
|
.value(db.settings.value, value.to_string())
|
||||||
|
.perform();
|
||||||
|
send_button_ = value;
|
||||||
|
send_button_update(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool enter_newline_;
|
||||||
|
public bool enter_newline {
|
||||||
|
get { return enter_newline_; }
|
||||||
|
set {
|
||||||
|
db.settings.upsert()
|
||||||
|
.value(db.settings.key, "enter_newline", true)
|
||||||
|
.value(db.settings.value, value.to_string())
|
||||||
|
.perform();
|
||||||
|
enter_newline_ = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public signal void dark_theme_update(bool is_dark);
|
||||||
|
private bool dark_theme_;
|
||||||
|
public bool dark_theme {
|
||||||
|
get { return dark_theme_; }
|
||||||
|
set {
|
||||||
|
db.settings.upsert()
|
||||||
|
.value(db.settings.key, "dark_theme", true)
|
||||||
|
.value(db.settings.value, value.to_string())
|
||||||
|
.perform();
|
||||||
|
dark_theme_ = value;
|
||||||
|
dark_theme_update(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,7 +60,7 @@ public class Dino.CallState : Object {
|
||||||
XmppStream stream = stream_interactor.get_stream(call.account);
|
XmppStream stream = stream_interactor.get_stream(call.account);
|
||||||
if (stream == null) return;
|
if (stream == null) return;
|
||||||
|
|
||||||
Gee.List<Jid> occupants = stream_interactor.get_module(MucManager.IDENTITY).get_other_occupants(muc, call.account);
|
Gee.List<Jid> occupants = stream_interactor.get_module(MucManager.IDENTITY).get_other_members(muc, call.account);
|
||||||
foreach (Jid occupant in occupants) {
|
foreach (Jid occupant in occupants) {
|
||||||
Jid? real_jid = stream_interactor.get_module(MucManager.IDENTITY).get_real_jid(occupant, call.account);
|
Jid? real_jid = stream_interactor.get_module(MucManager.IDENTITY).get_real_jid(occupant, call.account);
|
||||||
if (real_jid == null) continue;
|
if (real_jid == null) continue;
|
||||||
|
|
|
@ -11,6 +11,7 @@ public class ContentItemStore : StreamInteractionModule, Object {
|
||||||
public string id { get { return IDENTITY.id; } }
|
public string id { get { return IDENTITY.id; } }
|
||||||
|
|
||||||
public signal void new_item(ContentItem item, Conversation conversation);
|
public signal void new_item(ContentItem item, Conversation conversation);
|
||||||
|
public signal void history_loaded(Conversation conversation, ContentItem item, int count);
|
||||||
|
|
||||||
private StreamInteractor stream_interactor;
|
private StreamInteractor stream_interactor;
|
||||||
private Database db;
|
private Database db;
|
||||||
|
@ -241,8 +242,10 @@ public class ContentItemStore : StreamInteractionModule, Object {
|
||||||
// return ret;
|
// return ret;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
public Gee.List<ContentItem> get_before(Conversation conversation, ContentItem item, int count) {
|
public Gee.List<ContentItem> get_before(Conversation conversation, ContentItem item, int count, bool request_from_server = true) {
|
||||||
|
debug("Fetching earlier messages from the db");
|
||||||
long time = (long) item.time.to_unix();
|
long time = (long) item.time.to_unix();
|
||||||
|
|
||||||
QueryBuilder select = db.content_item.select()
|
QueryBuilder select = db.content_item.select()
|
||||||
.where(@"time < ? OR (time = ? AND id < ?)", { time.to_string(), time.to_string(), item.id.to_string() })
|
.where(@"time < ? OR (time = ? AND id < ?)", { time.to_string(), time.to_string(), item.id.to_string() })
|
||||||
.with(db.content_item.conversation_id, "=", conversation.id)
|
.with(db.content_item.conversation_id, "=", conversation.id)
|
||||||
|
@ -251,7 +254,18 @@ public class ContentItemStore : StreamInteractionModule, Object {
|
||||||
.order_by(db.content_item.id, "DESC")
|
.order_by(db.content_item.id, "DESC")
|
||||||
.limit(count);
|
.limit(count);
|
||||||
|
|
||||||
return get_items_from_query(select, conversation);
|
var items = get_items_from_query(select, conversation);
|
||||||
|
if (items.size == 0 && request_from_server) {
|
||||||
|
// Async request to get earlier messages from the server
|
||||||
|
var history_sync = stream_interactor.get_module(MessageProcessor.IDENTITY).history_sync;
|
||||||
|
history_sync.fetch_conversation_data.begin(conversation, item.time, (_, res) => {
|
||||||
|
history_sync.fetch_conversation_data.end(res);
|
||||||
|
debug("History loaded");
|
||||||
|
history_loaded(conversation, item, count);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return items;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Gee.List<ContentItem> get_after(Conversation conversation, ContentItem item, int count) {
|
public Gee.List<ContentItem> get_after(Conversation conversation, ContentItem item, int count) {
|
||||||
|
|
|
@ -46,6 +46,15 @@ public class FileManager : StreamInteractionModule, Object {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private string sanitize_filename(string filename) {
|
||||||
|
#if _WIN32
|
||||||
|
GLib.Regex regex = new GLib.Regex("[<>:\"/\\|?*]");
|
||||||
|
#else
|
||||||
|
GLib.Regex regex = new GLib.Regex("[/]");
|
||||||
|
#endif
|
||||||
|
return regex.replace(filename, -1, 0, "_");
|
||||||
|
}
|
||||||
|
|
||||||
public async void send_file(File file, Conversation conversation) {
|
public async void send_file(File file, Conversation conversation) {
|
||||||
FileTransfer file_transfer = new FileTransfer();
|
FileTransfer file_transfer = new FileTransfer();
|
||||||
file_transfer.account = conversation.account;
|
file_transfer.account = conversation.account;
|
||||||
|
@ -120,6 +129,7 @@ public class FileManager : StreamInteractionModule, Object {
|
||||||
}
|
}
|
||||||
|
|
||||||
yield file_sender.send_file(conversation, file_transfer, file_send_data, file_meta);
|
yield file_sender.send_file(conversation, file_transfer, file_send_data, file_meta);
|
||||||
|
file_transfer.state = FileTransfer.State.COMPLETE;
|
||||||
|
|
||||||
} catch (Error e) {
|
} catch (Error e) {
|
||||||
warning("Send file error: %s", e.message);
|
warning("Send file error: %s", e.message);
|
||||||
|
@ -242,7 +252,7 @@ public class FileManager : StreamInteractionModule, Object {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save file
|
// Save file
|
||||||
string filename = Random.next_int().to_string("%x") + "_" + file_transfer.file_name;
|
string filename = Random.next_int().to_string("%x") + "_" + sanitize_filename(file_transfer.file_name);
|
||||||
File file = File.new_for_path(Path.build_filename(get_storage_dir(), filename));
|
File file = File.new_for_path(Path.build_filename(get_storage_dir(), filename));
|
||||||
|
|
||||||
OutputStream os = file.create(FileCreateFlags.REPLACE_DESTINATION);
|
OutputStream os = file.create(FileCreateFlags.REPLACE_DESTINATION);
|
||||||
|
@ -250,6 +260,7 @@ public class FileManager : StreamInteractionModule, Object {
|
||||||
ssize_t read;
|
ssize_t read;
|
||||||
while ((read = yield input_stream.read_async(buffer, Priority.LOW, file_transfer.cancellable)) > 0) {
|
while ((read = yield input_stream.read_async(buffer, Priority.LOW, file_transfer.cancellable)) > 0) {
|
||||||
buffer.length = (int) read;
|
buffer.length = (int) read;
|
||||||
|
file_transfer.transferred_bytes += (uint64)read;
|
||||||
yield os.write_async(buffer, Priority.LOW, file_transfer.cancellable);
|
yield os.write_async(buffer, Priority.LOW, file_transfer.cancellable);
|
||||||
buffer.length = 1024;
|
buffer.length = 1024;
|
||||||
}
|
}
|
||||||
|
@ -297,6 +308,7 @@ public class FileManager : StreamInteractionModule, Object {
|
||||||
file_transfer.file_name = file_meta.file_name;
|
file_transfer.file_name = file_meta.file_name;
|
||||||
file_transfer.size = (int)file_meta.size;
|
file_transfer.size = (int)file_meta.size;
|
||||||
file_transfer.info = info;
|
file_transfer.info = info;
|
||||||
|
file_transfer.transferred_bytes = 0;
|
||||||
|
|
||||||
var encryption = file_provider.get_encryption(file_transfer, receive_data, file_meta);
|
var encryption = file_provider.get_encryption(file_transfer, receive_data, file_meta);
|
||||||
if (encryption != Encryption.NONE) file_transfer.encryption = encryption;
|
if (encryption != Encryption.NONE) file_transfer.encryption = encryption;
|
||||||
|
@ -329,11 +341,11 @@ public class FileManager : StreamInteractionModule, Object {
|
||||||
|
|
||||||
private async void save_file(FileTransfer file_transfer) throws FileSendError {
|
private async void save_file(FileTransfer file_transfer) throws FileSendError {
|
||||||
try {
|
try {
|
||||||
string filename = Random.next_int().to_string("%x") + "_" + file_transfer.file_name;
|
string filename = Random.next_int().to_string("%x") + "_" + sanitize_filename(file_transfer.file_name);
|
||||||
File file = File.new_for_path(Path.build_filename(get_storage_dir(), filename));
|
File file = File.new_for_path(Path.build_filename(get_storage_dir(), filename));
|
||||||
OutputStream os = file.create(FileCreateFlags.REPLACE_DESTINATION);
|
OutputStream os = file.create(FileCreateFlags.REPLACE_DESTINATION);
|
||||||
yield os.splice_async(file_transfer.input_stream, OutputStreamSpliceFlags.CLOSE_SOURCE|OutputStreamSpliceFlags.CLOSE_TARGET);
|
yield os.splice_async(file_transfer.input_stream, OutputStreamSpliceFlags.CLOSE_SOURCE|OutputStreamSpliceFlags.CLOSE_TARGET);
|
||||||
file_transfer.state = FileTransfer.State.COMPLETE;
|
file_transfer.state = FileTransfer.State.IN_PROGRESS;
|
||||||
file_transfer.path = filename;
|
file_transfer.path = filename;
|
||||||
file_transfer.input_stream = yield file.read_async();
|
file_transfer.input_stream = yield file.read_async();
|
||||||
} catch (Error e) {
|
} catch (Error e) {
|
||||||
|
|
|
@ -22,6 +22,7 @@ public class Dino.HistorySync {
|
||||||
public HashMap<Account, DateTime> catchup_until_time = new HashMap<Account, DateTime>(Account.hash_func, Account.equals_func);
|
public HashMap<Account, DateTime> catchup_until_time = new HashMap<Account, DateTime>(Account.hash_func, Account.equals_func);
|
||||||
|
|
||||||
private HashMap<string, Gee.List<Xmpp.MessageStanza>> stanzas = new HashMap<string, Gee.List<Xmpp.MessageStanza>>();
|
private HashMap<string, Gee.List<Xmpp.MessageStanza>> stanzas = new HashMap<string, Gee.List<Xmpp.MessageStanza>>();
|
||||||
|
private HashMap<string, int> messages_processed = new HashMap<string, int>();
|
||||||
|
|
||||||
public class HistorySync(Database db, StreamInteractor stream_interactor) {
|
public class HistorySync(Database db, StreamInteractor stream_interactor) {
|
||||||
this.stream_interactor = stream_interactor;
|
this.stream_interactor = stream_interactor;
|
||||||
|
@ -120,6 +121,94 @@ public class Dino.HistorySync {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async PageRequestResult fetch_messages(Account account, Xmpp.MessageArchiveManagement.V2.MamQueryParams query_params) {
|
||||||
|
debug("[%s | %s] Fetch query %s - %s", account.bare_jid.to_string(), query_params.mam_server.to_string(), query_params.start != null ? query_params.start.to_string() : "", query_params.end != null ? query_params.end.to_string() : "");
|
||||||
|
PageRequestResult? page_result = null;
|
||||||
|
|
||||||
|
int processed_pages = 0;
|
||||||
|
do {
|
||||||
|
page_result = yield get_mam_page(account, query_params, page_result, null);
|
||||||
|
processed_pages++;
|
||||||
|
|
||||||
|
debug("%d messages left to process, current page is %d", messages_processed[query_params.query_id], processed_pages);
|
||||||
|
if (messages_processed[query_params.query_id] <= 1) {
|
||||||
|
debug("Done processing new messages");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
debug("[%s | %s] Page result %s (got stanzas: %s)", account.bare_jid.to_string(), query_params.mam_server.to_string(), page_result.page_result.to_string(), (page_result.stanzas != null).to_string());
|
||||||
|
if (page_result.page_result == PageResult.Error || page_result.page_result == PageResult.Cancelled || page_result.query_result.first == null) {
|
||||||
|
return page_result;
|
||||||
|
}
|
||||||
|
|
||||||
|
} while (page_result.page_result == PageResult.MorePagesAvailable);
|
||||||
|
|
||||||
|
return page_result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async void fetch_data(Account account, Jid target, DateTime latest) {
|
||||||
|
debug("Fetch history for %s", target.to_string());
|
||||||
|
|
||||||
|
var query_params = new Xmpp.MessageArchiveManagement.V2.MamQueryParams.query_before(target, latest, null);
|
||||||
|
string query_id = query_params.query_id;
|
||||||
|
messages_processed[query_id] = HISTORY_SYNC_MAM_MESSAGES;
|
||||||
|
|
||||||
|
yield fetch_messages(account, query_params);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async void fetch_conversation_data(Conversation? conversation, DateTime latest) {
|
||||||
|
if (conversation == null) {
|
||||||
|
warning("Failed to fetch history, conversation is null");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var target = conversation.counterpart.bare_jid;
|
||||||
|
var account = conversation.account;
|
||||||
|
debug("Fetch history for %s", target.to_string());
|
||||||
|
|
||||||
|
var query_params = new Xmpp.MessageArchiveManagement.V2.MamQueryParams.query_before(target, latest, null);
|
||||||
|
if (conversation.type_ == Conversation.Type.CHAT) {
|
||||||
|
query_params.mam_server = account.bare_jid;
|
||||||
|
query_params.with = target;
|
||||||
|
}
|
||||||
|
|
||||||
|
string query_id = query_params.query_id;
|
||||||
|
messages_processed[query_id] = HISTORY_SYNC_MAM_MESSAGES;
|
||||||
|
|
||||||
|
yield fetch_messages(account, query_params);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async void fetch_history(Account account, Jid target, Cancellable? cancellable = null) {
|
||||||
|
debug("Fetch history for %s", target.to_string());
|
||||||
|
|
||||||
|
RowOption latest_row_opt = db.mam_catchup.select()
|
||||||
|
.with(db.mam_catchup.account_id, "=", account.id)
|
||||||
|
.with(db.mam_catchup.server_jid, "=", target.to_string())
|
||||||
|
.with(db.mam_catchup.to_time, ">=", (long) new DateTime.from_unix_utc(0).to_unix())
|
||||||
|
.order_by(db.mam_catchup.to_time, "DESC")
|
||||||
|
.single().row();
|
||||||
|
Row? latest_row = latest_row_opt.is_present() ? latest_row_opt.inner : null;
|
||||||
|
|
||||||
|
int? db_id = null;
|
||||||
|
string? latest_id = null;
|
||||||
|
if (latest_row != null) {
|
||||||
|
// Local mam catchup data exists so we can filter messages based on the latest id
|
||||||
|
db_id = latest_row[db.mam_catchup.id];
|
||||||
|
latest_id = latest_row[db.mam_catchup.from_id];
|
||||||
|
}
|
||||||
|
|
||||||
|
DateTime latest_time = new DateTime.now();
|
||||||
|
Xmpp.MessageArchiveManagement.V2.MamQueryParams query_params;
|
||||||
|
query_params = new Xmpp.MessageArchiveManagement.V2.MamQueryParams.query_before(target, latest_time, latest_id);
|
||||||
|
|
||||||
|
if (db_id == null) {
|
||||||
|
query_params.mam_server = account.bare_jid;
|
||||||
|
query_params.with = target;
|
||||||
|
}
|
||||||
|
|
||||||
|
yield fetch_query(account, query_params, db_id, cancellable);
|
||||||
|
}
|
||||||
|
|
||||||
public async void fetch_everything(Account account, Jid mam_server, Cancellable? cancellable = null, DateTime until_earliest_time = new DateTime.from_unix_utc(0)) {
|
public async void fetch_everything(Account account, Jid mam_server, Cancellable? cancellable = null, DateTime until_earliest_time = new DateTime.from_unix_utc(0)) {
|
||||||
debug("Fetch everything for %s %s", mam_server.to_string(), until_earliest_time != null ? @"(until $until_earliest_time)" : "");
|
debug("Fetch everything for %s %s", mam_server.to_string(), until_earliest_time != null ? @"(until $until_earliest_time)" : "");
|
||||||
RowOption latest_row_opt = db.mam_catchup.select()
|
RowOption latest_row_opt = db.mam_catchup.select()
|
||||||
|
@ -321,7 +410,7 @@ public class Dino.HistorySync {
|
||||||
* Iteratively fetches all pages returned for a query (until a PageResult other than MorePagesAvailable is returned)
|
* Iteratively fetches all pages returned for a query (until a PageResult other than MorePagesAvailable is returned)
|
||||||
* @return The last PageRequestResult result
|
* @return The last PageRequestResult result
|
||||||
**/
|
**/
|
||||||
private async PageRequestResult fetch_query(Account account, Xmpp.MessageArchiveManagement.V2.MamQueryParams query_params, int db_id, Cancellable? cancellable = null) {
|
private async PageRequestResult fetch_query(Account account, Xmpp.MessageArchiveManagement.V2.MamQueryParams query_params, int? db_id, Cancellable? cancellable = null) {
|
||||||
debug("[%s | %s] Fetch query %s - %s", account.bare_jid.to_string(), query_params.mam_server.to_string(), query_params.start != null ? query_params.start.to_string() : "", query_params.end != null ? query_params.end.to_string() : "");
|
debug("[%s | %s] Fetch query %s - %s", account.bare_jid.to_string(), query_params.mam_server.to_string(), query_params.start != null ? query_params.start.to_string() : "", query_params.end != null ? query_params.end.to_string() : "");
|
||||||
PageRequestResult? page_result = null;
|
PageRequestResult? page_result = null;
|
||||||
do {
|
do {
|
||||||
|
@ -333,6 +422,8 @@ public class Dino.HistorySync {
|
||||||
string earliest_mam_id = page_result.query_result.first;
|
string earliest_mam_id = page_result.query_result.first;
|
||||||
long earliest_mam_time = (long)mam_times[account][earliest_mam_id].to_unix();
|
long earliest_mam_time = (long)mam_times[account][earliest_mam_id].to_unix();
|
||||||
|
|
||||||
|
if (db_id != null) {
|
||||||
|
// Update local mam catchup data if it exists
|
||||||
debug("Updating %s to %s, %s", query_params.mam_server.to_string(), earliest_mam_time.to_string(), earliest_mam_id);
|
debug("Updating %s to %s, %s", query_params.mam_server.to_string(), earliest_mam_time.to_string(), earliest_mam_id);
|
||||||
var query = db.mam_catchup.update()
|
var query = db.mam_catchup.update()
|
||||||
.with(db.mam_catchup.id, "=", db_id)
|
.with(db.mam_catchup.id, "=", db_id)
|
||||||
|
@ -344,6 +435,8 @@ public class Dino.HistorySync {
|
||||||
query.set(db.mam_catchup.from_end, true);
|
query.set(db.mam_catchup.from_end, true);
|
||||||
}
|
}
|
||||||
query.perform();
|
query.perform();
|
||||||
|
}
|
||||||
|
|
||||||
} while (page_result.page_result == PageResult.MorePagesAvailable);
|
} while (page_result.page_result == PageResult.MorePagesAvailable);
|
||||||
|
|
||||||
return page_result;
|
return page_result;
|
||||||
|
@ -413,6 +506,7 @@ public class Dino.HistorySync {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hitted_range.has_key(query_id) && hitted_range[query_id] == -2) {
|
if (hitted_range.has_key(query_id) && hitted_range[query_id] == -2) {
|
||||||
// Message got filtered out by xmpp-vala, but succesful range fetch nevertheless
|
// Message got filtered out by xmpp-vala, but succesful range fetch nevertheless
|
||||||
yield send_messages_back_into_pipeline(account, query_id);
|
yield send_messages_back_into_pipeline(account, query_id);
|
||||||
|
@ -427,15 +521,24 @@ public class Dino.HistorySync {
|
||||||
if (cancellable != null && cancellable.is_cancelled()) {
|
if (cancellable != null && cancellable.is_cancelled()) {
|
||||||
page_result = PageResult.Cancelled;
|
page_result = PageResult.Cancelled;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new PageRequestResult(page_result, query_result, stanzas_for_query);
|
return new PageRequestResult(page_result, query_result, stanzas_for_query);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void send_messages_back_into_pipeline(Account account, string query_id, Cancellable? cancellable = null) {
|
private async void send_messages_back_into_pipeline(Account account, string query_id, Cancellable? cancellable = null) {
|
||||||
if (!stanzas.has_key(query_id)) return;
|
if (!stanzas.has_key(query_id)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
foreach (Xmpp.MessageStanza message in stanzas[query_id]) {
|
foreach (Xmpp.MessageStanza message in stanzas[query_id]) {
|
||||||
if (cancellable != null && cancellable.is_cancelled()) break;
|
if (cancellable != null && cancellable.is_cancelled()) break;
|
||||||
yield stream_interactor.get_module(MessageProcessor.IDENTITY).run_pipeline_announce(account, message);
|
bool result = yield stream_interactor.get_module(MessageProcessor.IDENTITY).run_pipeline_announce(account, message);
|
||||||
|
|
||||||
|
if (result && messages_processed.has_key(query_id)) {
|
||||||
|
int count = messages_processed[query_id];
|
||||||
|
count = count - 1;
|
||||||
|
messages_processed[query_id] = count;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
stanzas.unset(query_id);
|
stanzas.unset(query_id);
|
||||||
}
|
}
|
||||||
|
|
|
@ -220,7 +220,19 @@ public class JingleFileSender : FileSender, Object {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
yield stream.get_module(Xep.JingleFileTransfer.Module.IDENTITY).offer_file_stream(stream, full_jid, file_transfer.input_stream, file_transfer.server_file_name, file_meta.size, precondition_name, precondition_options);
|
var? module = stream.get_module(Xep.JingleFileTransfer.Module.IDENTITY);
|
||||||
|
|
||||||
|
if (module == null)
|
||||||
|
throw new FileSendError.UPLOAD_FAILED("unexpected null module");
|
||||||
|
|
||||||
|
module.transferred_bytes.connect((bytes) => {
|
||||||
|
file_transfer.transferred_bytes += bytes;
|
||||||
|
});
|
||||||
|
|
||||||
|
yield module.offer_file_stream(stream, full_jid,
|
||||||
|
file_transfer.cancellable, file_transfer.input_stream,
|
||||||
|
file_transfer.server_file_name, file_meta.size,
|
||||||
|
precondition_name, precondition_options);
|
||||||
} catch (Error e) {
|
} catch (Error e) {
|
||||||
throw new FileSendError.UPLOAD_FAILED(@"offer_file_stream failed: $(e.message)");
|
throw new FileSendError.UPLOAD_FAILED(@"offer_file_stream failed: $(e.message)");
|
||||||
}
|
}
|
||||||
|
|
|
@ -130,14 +130,18 @@ public class MessageProcessor : StreamInteractionModule, Object {
|
||||||
run_pipeline_announce.begin(account, message_stanza);
|
run_pipeline_announce.begin(account, message_stanza);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async void run_pipeline_announce(Account account, Xmpp.MessageStanza message_stanza) {
|
public async bool run_pipeline_announce(Account account, Xmpp.MessageStanza message_stanza) {
|
||||||
Entities.Message message = yield parse_message_stanza(account, message_stanza);
|
Entities.Message message = yield parse_message_stanza(account, message_stanza);
|
||||||
|
|
||||||
Conversation? conversation = stream_interactor.get_module(ConversationManager.IDENTITY).get_conversation_for_message(message);
|
Conversation? conversation = stream_interactor.get_module(ConversationManager.IDENTITY).get_conversation_for_message(message);
|
||||||
if (conversation == null) return;
|
if (conversation == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool abort = yield received_pipeline.run(message, message_stanza, conversation);
|
bool abort = yield received_pipeline.run(message, message_stanza, conversation);
|
||||||
if (abort) return;
|
if (abort) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (message.direction == Entities.Message.DIRECTION_RECEIVED) {
|
if (message.direction == Entities.Message.DIRECTION_RECEIVED) {
|
||||||
message_received(message, conversation);
|
message_received(message, conversation);
|
||||||
|
@ -146,6 +150,7 @@ public class MessageProcessor : StreamInteractionModule, Object {
|
||||||
}
|
}
|
||||||
|
|
||||||
message_sent_or_received(message, conversation);
|
message_sent_or_received(message, conversation);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Entities.Message parse_message_stanza(Account account, Xmpp.MessageStanza message) {
|
public async Entities.Message parse_message_stanza(Account account, Xmpp.MessageStanza message) {
|
||||||
|
@ -245,6 +250,7 @@ public class MessageProcessor : StreamInteractionModule, Object {
|
||||||
|
|
||||||
// If the message is a duplicate
|
// If the message is a duplicate
|
||||||
if (builder.count() > 0) {
|
if (builder.count() > 0) {
|
||||||
|
warning("deduplicate by server id");
|
||||||
history_sync.on_server_id_duplicate(account, stanza, message);
|
history_sync.on_server_id_duplicate(account, stanza, message);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -271,6 +277,11 @@ public class MessageProcessor : StreamInteractionModule, Object {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bool duplicate = builder.single().row().is_present();
|
bool duplicate = builder.single().row().is_present();
|
||||||
|
|
||||||
|
if (duplicate) {
|
||||||
|
warning("deduplicate by uuid");
|
||||||
|
}
|
||||||
|
|
||||||
return duplicate;
|
return duplicate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -291,7 +302,13 @@ public class MessageProcessor : StreamInteractionModule, Object {
|
||||||
} else {
|
} else {
|
||||||
builder.with_null(db.message.counterpart_resource);
|
builder.with_null(db.message.counterpart_resource);
|
||||||
}
|
}
|
||||||
return builder.count() > 0;
|
|
||||||
|
bool duplicate = builder.count() > 0;
|
||||||
|
if (duplicate) {
|
||||||
|
warning("deduplicate by content and metadata");
|
||||||
|
}
|
||||||
|
|
||||||
|
return duplicate;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class DeduplicateMessageListener : MessageListener {
|
private class DeduplicateMessageListener : MessageListener {
|
||||||
|
@ -357,7 +374,10 @@ public class MessageProcessor : StreamInteractionModule, Object {
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async bool run(Entities.Message message, Xmpp.MessageStanza stanza, Conversation conversation) {
|
public override async bool run(Entities.Message message, Xmpp.MessageStanza stanza, Conversation conversation) {
|
||||||
if (message.body == null) return true;
|
if (message.body == null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
stream_interactor.get_module(ContentItemStore.IDENTITY).insert_message(message, conversation);
|
stream_interactor.get_module(ContentItemStore.IDENTITY).insert_message(message, conversation);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -106,8 +106,8 @@ public class MucManager : StreamInteractionModule, Object {
|
||||||
if (can_do_mam) {
|
if (can_do_mam) {
|
||||||
var history_sync = stream_interactor.get_module(MessageProcessor.IDENTITY).history_sync;
|
var history_sync = stream_interactor.get_module(MessageProcessor.IDENTITY).history_sync;
|
||||||
if (conversation == null) {
|
if (conversation == null) {
|
||||||
// We never joined the conversation before, just fetch the latest MAM page
|
// We never joined the conversation before, fetch latest MAM pages
|
||||||
yield history_sync.fetch_latest_page(account, jid.bare_jid, null, new DateTime.from_unix_utc(0), cancellable);
|
yield history_sync.fetch_data(account, jid.bare_jid, new DateTime.now());
|
||||||
} else {
|
} else {
|
||||||
// Fetch everything up to the last time the user actively joined
|
// Fetch everything up to the last time the user actively joined
|
||||||
if (!mucs_sync_cancellables.has_key(account)) {
|
if (!mucs_sync_cancellables.has_key(account)) {
|
||||||
|
@ -259,7 +259,23 @@ public class MucManager : StreamInteractionModule, Object {
|
||||||
return is_groupchat(jid, account) && !is_private_room(account, jid);
|
return is_groupchat(jid, account) && !is_private_room(account, jid);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Gee.List<Jid>? get_occupants(Jid jid, Account account) {
|
public Gee.List<Jid>? get_all_members(Jid jid, Account account) {
|
||||||
|
if (is_groupchat(jid, account)) {
|
||||||
|
Gee.List<Jid> ret = new ArrayList<Jid>(Jid.equals_func);
|
||||||
|
|
||||||
|
// This should return all members of the chat
|
||||||
|
Gee.List<Jid>? members = get_offline_members(jid, account);
|
||||||
|
if (members != null) {
|
||||||
|
ret.add_all(members);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Gee.List<Jid>? get_members(Jid jid, Account account) {
|
||||||
if (is_groupchat(jid, account)) {
|
if (is_groupchat(jid, account)) {
|
||||||
Gee.List<Jid> ret = new ArrayList<Jid>(Jid.equals_func);
|
Gee.List<Jid> ret = new ArrayList<Jid>(Jid.equals_func);
|
||||||
Gee.List<Jid>? full_jids = stream_interactor.get_module(PresenceManager.IDENTITY).get_full_jids(jid, account);
|
Gee.List<Jid>? full_jids = stream_interactor.get_module(PresenceManager.IDENTITY).get_full_jids(jid, account);
|
||||||
|
@ -268,18 +284,21 @@ public class MucManager : StreamInteractionModule, Object {
|
||||||
// Remove eventual presence from bare jid
|
// Remove eventual presence from bare jid
|
||||||
ret.remove(jid);
|
ret.remove(jid);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Gee.List<Jid>? get_other_occupants(Jid jid, Account account) {
|
public Gee.List<Jid>? get_other_members(Jid jid, Account account) {
|
||||||
Gee.List<Jid>? occupants = get_occupants(jid, account);
|
Gee.List<Jid>? members = get_members(jid, account);
|
||||||
Jid? own_jid = get_own_jid(jid, account);
|
Jid? own_jid = get_own_jid(jid, account);
|
||||||
if (occupants != null && own_jid != null) {
|
if (members != null && own_jid != null) {
|
||||||
occupants.remove(own_jid);
|
members.remove(own_jid);
|
||||||
}
|
}
|
||||||
return occupants;
|
|
||||||
|
return members;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool is_groupchat(Jid jid, Account account) {
|
public bool is_groupchat(Jid jid, Account account) {
|
||||||
|
@ -535,12 +554,25 @@ public class MucManager : StreamInteractionModule, Object {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void on_invite_received(Account account, Jid room_jid, Jid from_jid, string? password, string? reason) {
|
private void on_invite_received(Account account, Jid room_jid, Jid from_jid, string? password, string? reason) {
|
||||||
|
info("Invite received for room %s", room_jid.bare_jid.to_string());
|
||||||
|
Gee.List<Conversation> conversations = stream_interactor.get_module(ConversationManager.IDENTITY).get_active_conversations(account);
|
||||||
|
foreach (Conversation conversation in conversations) {
|
||||||
|
if (conversation.counterpart.bare_jid.to_string() == room_jid.bare_jid.to_string()) {
|
||||||
|
// HACK: try to skip duplicate invites for active conversations
|
||||||
|
warning("Skipping duplicate invite for conversation %s", room_jid.bare_jid.to_string());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!invites.has_key(account)) {
|
if (!invites.has_key(account)) {
|
||||||
invites[account] = new LinkedList<Jid>(Jid.equals_func);
|
invites[account] = new LinkedList<Jid>(Jid.equals_func);
|
||||||
}
|
}
|
||||||
if (invites[account].contains(room_jid)) return;
|
|
||||||
invites[account].add(room_jid);
|
|
||||||
|
|
||||||
|
if (invites[account].contains(room_jid)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
invites[account].add(room_jid);
|
||||||
invite_received(account, room_jid, from_jid, password, reason);
|
invite_received(account, room_jid, from_jid, password, reason);
|
||||||
|
|
||||||
Timeout.add_seconds(5, () => {
|
Timeout.add_seconds(5, () => {
|
||||||
|
@ -596,8 +628,8 @@ public class MucManager : StreamInteractionModule, Object {
|
||||||
private void set_autojoin(Account account, XmppStream stream, Jid jid, string? nick, string? password) {
|
private void set_autojoin(Account account, XmppStream stream, Jid jid, string? nick, string? password) {
|
||||||
bookmarks_provider[account].get_conferences.begin(stream, (_, res) => {
|
bookmarks_provider[account].get_conferences.begin(stream, (_, res) => {
|
||||||
Set<Conference>? conferences = bookmarks_provider[account].get_conferences.end(res);
|
Set<Conference>? conferences = bookmarks_provider[account].get_conferences.end(res);
|
||||||
if (conferences == null) return;
|
|
||||||
|
|
||||||
|
if (conferences != null) {
|
||||||
foreach (Conference conference in conferences) {
|
foreach (Conference conference in conferences) {
|
||||||
if (conference.jid.equals(jid)) {
|
if (conference.jid.equals(jid)) {
|
||||||
if (!conference.autojoin) {
|
if (!conference.autojoin) {
|
||||||
|
@ -607,6 +639,8 @@ public class MucManager : StreamInteractionModule, Object {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Conference changed = new Xep.Bookmarks.Bookmarks1Conference(jid) { nick=nick, password=password, autojoin=true };
|
Conference changed = new Xep.Bookmarks.Bookmarks1Conference(jid) { nick=nick, password=password, autojoin=true };
|
||||||
bookmarks_provider[account].add_conference.begin(stream, changed);
|
bookmarks_provider[account].add_conference.begin(stream, changed);
|
||||||
});
|
});
|
||||||
|
|
|
@ -12,9 +12,7 @@ public class NotificationEvents : StreamInteractionModule, Object {
|
||||||
public signal void notify_content_item(ContentItem content_item, Conversation conversation);
|
public signal void notify_content_item(ContentItem content_item, Conversation conversation);
|
||||||
|
|
||||||
private StreamInteractor stream_interactor;
|
private StreamInteractor stream_interactor;
|
||||||
private Future<NotificationProvider> notifier;
|
private Gee.List<Promise<NotificationProvider>> promises = new ArrayList<Promise<NotificationProvider>>();
|
||||||
private Promise<NotificationProvider> notifier_promise;
|
|
||||||
private bool notifier_outstanding = true;
|
|
||||||
|
|
||||||
public static void start(StreamInteractor stream_interactor) {
|
public static void start(StreamInteractor stream_interactor) {
|
||||||
NotificationEvents m = new NotificationEvents(stream_interactor);
|
NotificationEvents m = new NotificationEvents(stream_interactor);
|
||||||
|
@ -31,18 +29,16 @@ public class NotificationEvents : StreamInteractionModule, Object {
|
||||||
stream_interactor.get_module(MucManager.IDENTITY).voice_request_received.connect((account, room_jid, from_jid, nick) => on_voice_request_received.begin(account, room_jid, from_jid, nick));
|
stream_interactor.get_module(MucManager.IDENTITY).voice_request_received.connect((account, room_jid, from_jid, nick) => on_voice_request_received.begin(account, room_jid, from_jid, nick));
|
||||||
|
|
||||||
stream_interactor.get_module(Calls.IDENTITY).call_incoming.connect((call, state, conversation, video, multiparty) => on_call_incoming.begin(call, state, conversation, video, multiparty));
|
stream_interactor.get_module(Calls.IDENTITY).call_incoming.connect((call, state, conversation, video, multiparty) => on_call_incoming.begin(call, state, conversation, video, multiparty));
|
||||||
|
stream_interactor.get_module(Calls.IDENTITY).call_outgoing.connect((call, state, conversation) => on_call_outgoing.begin(call));
|
||||||
|
|
||||||
stream_interactor.connection_manager.connection_error.connect((account, error) => on_connection_error.begin(account, error));
|
stream_interactor.connection_manager.connection_error.connect((account, error) => on_connection_error.begin(account, error));
|
||||||
stream_interactor.get_module(ChatInteraction.IDENTITY).focused_in.connect((conversation) => on_focused_in.begin(conversation));
|
stream_interactor.get_module(ChatInteraction.IDENTITY).focused_in.connect((conversation) => on_focused_in.begin(conversation));
|
||||||
|
|
||||||
notifier_promise = new Promise<NotificationProvider>();
|
|
||||||
notifier = notifier_promise.future;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async void register_notification_provider(NotificationProvider notification_provider) {
|
public async void register_notification_provider(NotificationProvider notification_provider) {
|
||||||
if (notifier_outstanding || (yield notifier.wait_async()).get_priority() < notification_provider.get_priority()) {
|
var promise = new Promise<NotificationProvider>();
|
||||||
notifier_outstanding = false;
|
promise.set_value(notification_provider);
|
||||||
notifier_promise.set_value(notification_provider);
|
promises.add(promise);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void on_content_item_received(ContentItem item, Conversation conversation) {
|
private async void on_content_item_received(ContentItem item, Conversation conversation) {
|
||||||
|
@ -77,9 +73,11 @@ public class NotificationEvents : StreamInteractionModule, Object {
|
||||||
|
|
||||||
notify_content_item(item, conversation);
|
notify_content_item(item, conversation);
|
||||||
if (notify != Conversation.NotifySetting.OFF) {
|
if (notify != Conversation.NotifySetting.OFF) {
|
||||||
NotificationProvider notifier = yield notifier.wait_async();
|
foreach(var promise in promises) {
|
||||||
|
NotificationProvider notifier = yield promise.future.wait_async();
|
||||||
yield notifier.notify_message(message, conversation, conversation_display_name, participant_display_name);
|
yield notifier.notify_message(message, conversation, conversation_display_name, participant_display_name);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case FileItem.TYPE:
|
case FileItem.TYPE:
|
||||||
FileTransfer file_transfer = ((FileItem) item).file_transfer;
|
FileTransfer file_transfer = ((FileItem) item).file_transfer;
|
||||||
|
@ -91,9 +89,11 @@ public class NotificationEvents : StreamInteractionModule, Object {
|
||||||
|
|
||||||
notify_content_item(item, conversation);
|
notify_content_item(item, conversation);
|
||||||
if (notify != Conversation.NotifySetting.OFF) {
|
if (notify != Conversation.NotifySetting.OFF) {
|
||||||
NotificationProvider notifier = yield notifier.wait_async();
|
foreach(var promise in promises) {
|
||||||
|
NotificationProvider notifier = yield promise.future.wait_async();
|
||||||
yield notifier.notify_file(file_transfer, conversation, is_image, conversation_display_name, participant_display_name);
|
yield notifier.notify_file(file_transfer, conversation, is_image, conversation_display_name, participant_display_name);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case CallItem.TYPE:
|
case CallItem.TYPE:
|
||||||
// handled in `on_call_incoming`
|
// handled in `on_call_incoming`
|
||||||
|
@ -105,23 +105,28 @@ public class NotificationEvents : StreamInteractionModule, Object {
|
||||||
Conversation? conversation = stream_interactor.get_module(ConversationManager.IDENTITY).get_conversation(room_jid, account, Conversation.Type.GROUPCHAT);
|
Conversation? conversation = stream_interactor.get_module(ConversationManager.IDENTITY).get_conversation(room_jid, account, Conversation.Type.GROUPCHAT);
|
||||||
if (conversation == null) return;
|
if (conversation == null) return;
|
||||||
|
|
||||||
NotificationProvider notifier = yield notifier.wait_async();
|
foreach(var promise in promises) {
|
||||||
|
NotificationProvider notifier = yield promise.future.wait_async();
|
||||||
yield notifier.notify_voice_request(conversation, from_jid);
|
yield notifier.notify_voice_request(conversation, from_jid);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private async void on_received_subscription_request(Jid jid, Account account) {
|
private async void on_received_subscription_request(Jid jid, Account account) {
|
||||||
Conversation conversation = stream_interactor.get_module(ConversationManager.IDENTITY).create_conversation(jid, account, Conversation.Type.CHAT);
|
Conversation conversation = stream_interactor.get_module(ConversationManager.IDENTITY).create_conversation(jid, account, Conversation.Type.CHAT);
|
||||||
if (stream_interactor.get_module(ChatInteraction.IDENTITY).is_active_focus(conversation)) return;
|
if (stream_interactor.get_module(ChatInteraction.IDENTITY).is_active_focus(conversation)) return;
|
||||||
|
|
||||||
NotificationProvider notifier = yield notifier.wait_async();
|
foreach(var promise in promises) {
|
||||||
|
NotificationProvider notifier = yield promise.future.wait_async();
|
||||||
yield notifier.notify_subscription_request(conversation);
|
yield notifier.notify_subscription_request(conversation);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private async void on_call_incoming(Call call, CallState call_state, Conversation conversation, bool video, bool multiparty) {
|
private async void on_call_incoming(Call call, CallState call_state, Conversation conversation, bool video, bool multiparty) {
|
||||||
if (!stream_interactor.get_module(Calls.IDENTITY).can_we_do_calls(call.account)) return;
|
if (!stream_interactor.get_module(Calls.IDENTITY).can_we_do_calls(call.account)) return;
|
||||||
string conversation_display_name = get_conversation_display_name(stream_interactor, conversation, null);
|
string conversation_display_name = get_conversation_display_name(stream_interactor, conversation, null);
|
||||||
|
|
||||||
NotificationProvider notifier = yield notifier.wait_async();
|
foreach(var promise in promises) {
|
||||||
|
NotificationProvider notifier = yield promise.future.wait_async();
|
||||||
yield notifier.notify_call(call, conversation, video, multiparty, conversation_display_name);
|
yield notifier.notify_call(call, conversation, video, multiparty, conversation_display_name);
|
||||||
call.notify["state"].connect(() => {
|
call.notify["state"].connect(() => {
|
||||||
if (call.state != Call.State.RINGING) {
|
if (call.state != Call.State.RINGING) {
|
||||||
|
@ -129,6 +134,19 @@ public class NotificationEvents : StreamInteractionModule, Object {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void on_call_outgoing(Call call) {
|
||||||
|
foreach(var promise in promises) {
|
||||||
|
NotificationProvider notifier = yield promise.future.wait_async();
|
||||||
|
yield notifier.notify_dialing();
|
||||||
|
call.notify["state"].connect(() => {
|
||||||
|
if (call.state != Call.State.ESTABLISHING) {
|
||||||
|
notifier.retract_dialing.begin();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private async void on_invite_received(Account account, Jid room_jid, Jid from_jid, string? password, string? reason) {
|
private async void on_invite_received(Account account, Jid room_jid, Jid from_jid, string? password, string? reason) {
|
||||||
string inviter_display_name;
|
string inviter_display_name;
|
||||||
|
@ -139,20 +157,27 @@ public class NotificationEvents : StreamInteractionModule, Object {
|
||||||
Conversation direct_conversation = new Conversation(from_jid, account, Conversation.Type.CHAT);
|
Conversation direct_conversation = new Conversation(from_jid, account, Conversation.Type.CHAT);
|
||||||
inviter_display_name = get_participant_display_name(stream_interactor, direct_conversation, from_jid);
|
inviter_display_name = get_participant_display_name(stream_interactor, direct_conversation, from_jid);
|
||||||
}
|
}
|
||||||
NotificationProvider notifier = yield notifier.wait_async();
|
|
||||||
|
foreach(var promise in promises) {
|
||||||
|
NotificationProvider notifier = yield promise.future.wait_async();
|
||||||
yield notifier.notify_muc_invite(account, room_jid, from_jid, inviter_display_name);
|
yield notifier.notify_muc_invite(account, room_jid, from_jid, inviter_display_name);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private async void on_connection_error(Account account, ConnectionManager.ConnectionError error) {
|
private async void on_connection_error(Account account, ConnectionManager.ConnectionError error) {
|
||||||
NotificationProvider notifier = yield notifier.wait_async();
|
foreach(var promise in promises) {
|
||||||
|
NotificationProvider notifier = yield promise.future.wait_async();
|
||||||
yield notifier.notify_connection_error(account, error);
|
yield notifier.notify_connection_error(account, error);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private async void on_focused_in(Conversation conversation) {
|
private async void on_focused_in(Conversation conversation) {
|
||||||
NotificationProvider notifier = yield notifier.wait_async();
|
foreach(var promise in promises) {
|
||||||
|
NotificationProvider notifier = yield promise.future.wait_async();
|
||||||
yield notifier.retract_content_item_notifications();
|
yield notifier.retract_content_item_notifications();
|
||||||
yield notifier.retract_conversation_notifications(conversation);
|
yield notifier.retract_conversation_notifications(conversation);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface NotificationProvider : Object {
|
public interface NotificationProvider : Object {
|
||||||
|
@ -162,6 +187,8 @@ public interface NotificationProvider : Object {
|
||||||
public abstract async void notify_file(FileTransfer file_transfer, Conversation conversation, bool is_image, string conversation_display_name, string? participant_display_name);
|
public abstract async void notify_file(FileTransfer file_transfer, Conversation conversation, bool is_image, string conversation_display_name, string? participant_display_name);
|
||||||
public abstract async void notify_call(Call call, Conversation conversation, bool video, bool multiparty, string conversation_display_name);
|
public abstract async void notify_call(Call call, Conversation conversation, bool video, bool multiparty, string conversation_display_name);
|
||||||
public abstract async void retract_call_notification(Call call, Conversation conversation);
|
public abstract async void retract_call_notification(Call call, Conversation conversation);
|
||||||
|
public abstract async void notify_dialing();
|
||||||
|
public abstract async void retract_dialing();
|
||||||
public abstract async void notify_subscription_request(Conversation conversation);
|
public abstract async void notify_subscription_request(Conversation conversation);
|
||||||
public abstract async void notify_connection_error(Account account, ConnectionManager.ConnectionError error);
|
public abstract async void notify_connection_error(Account account, ConnectionManager.ConnectionError error);
|
||||||
public abstract async void notify_muc_invite(Account account, Jid room_jid, Jid from_jid, string inviter_display_name);
|
public abstract async void notify_muc_invite(Account account, Jid room_jid, Jid from_jid, string inviter_display_name);
|
||||||
|
|
|
@ -71,6 +71,12 @@ public class Register : StreamInteractionModule, Object{
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async string? change_password(Account account, string new_pw){
|
||||||
|
XmppStream stream = stream_interactor.get_stream(account);
|
||||||
|
if (stream == null) return "Connection unavailable";
|
||||||
|
return yield stream.get_module(Xep.InBandRegistration.Module.IDENTITY).change_password(stream, account.full_jid, new_pw);
|
||||||
|
}
|
||||||
|
|
||||||
public class ServerAvailabilityReturn {
|
public class ServerAvailabilityReturn {
|
||||||
public bool available { get; set; }
|
public bool available { get; set; }
|
||||||
public TlsCertificateFlags? error_flags { get; set; }
|
public TlsCertificateFlags? error_flags { get; set; }
|
||||||
|
@ -229,3 +235,4 @@ public class Register : StreamInteractionModule, Object{
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ namespace Dino {
|
||||||
public class Util {
|
public class Util {
|
||||||
#if _WIN32
|
#if _WIN32
|
||||||
[CCode (cname = "ShellExecuteA", cheader_filename = "windows.h")]
|
[CCode (cname = "ShellExecuteA", cheader_filename = "windows.h")]
|
||||||
private static extern int ShellExecuteA(int* hwnd, string operation, string file, string parameters, string directory, int showCmd);
|
private static extern int* ShellExecuteA(int* hwnd, string operation, string file, string parameters, string directory, int showCmd);
|
||||||
|
|
||||||
[CCode (cname = "CoInitialize", cheader_filename = "windows.h")]
|
[CCode (cname = "CoInitialize", cheader_filename = "windows.h")]
|
||||||
private static extern int CoInitialize(void* reserved);
|
private static extern int CoInitialize(void* reserved);
|
||||||
|
@ -14,7 +14,7 @@ public class Util {
|
||||||
[CCode (cname = "CoUninitialize", cheader_filename = "windows.h")]
|
[CCode (cname = "CoUninitialize", cheader_filename = "windows.h")]
|
||||||
private static extern void CoUninitialize();
|
private static extern void CoUninitialize();
|
||||||
|
|
||||||
private static int ShellExecute(string operation, string file) {
|
private static int* ShellExecute(string operation, string file) {
|
||||||
CoInitialize(null);
|
CoInitialize(null);
|
||||||
var result = ShellExecuteA(null, operation, file, null, null, 1);
|
var result = ShellExecuteA(null, operation, file, null, null, 1);
|
||||||
CoUninitialize();
|
CoUninitialize();
|
||||||
|
|
|
@ -2,6 +2,7 @@ namespace Dino {
|
||||||
|
|
||||||
private extern const string SYSTEM_LIBDIR_NAME;
|
private extern const string SYSTEM_LIBDIR_NAME;
|
||||||
private extern const string SYSTEM_PLUGIN_DIR;
|
private extern const string SYSTEM_PLUGIN_DIR;
|
||||||
|
private extern const string SYSTEM_LOCALEDIR_NAME;
|
||||||
|
|
||||||
public class SearchPathGenerator {
|
public class SearchPathGenerator {
|
||||||
|
|
||||||
|
@ -12,14 +13,21 @@ public class SearchPathGenerator {
|
||||||
}
|
}
|
||||||
|
|
||||||
public string get_locale_path(string gettext_package, string locale_install_dir) {
|
public string get_locale_path(string gettext_package, string locale_install_dir) {
|
||||||
string? locale_dir = null;
|
if (exec_path != null) {
|
||||||
if (Path.get_dirname(exec_path).contains("dino") || Path.get_dirname(exec_path) == "." || Path.get_dirname(exec_path).contains("build")) {
|
var exec_dir = Path.get_dirname(exec_path);
|
||||||
string exec_locale = Path.build_filename(Path.get_dirname(exec_path), "locale");
|
string[] search_paths = new string[] {
|
||||||
if (FileUtils.test(Path.build_filename(exec_locale, "en", "LC_MESSAGES", gettext_package + ".mo"), FileTest.IS_REGULAR)) {
|
Path.build_filename(exec_dir, "locale"),
|
||||||
locale_dir = exec_locale;
|
Path.build_filename(Path.get_dirname(exec_dir), SYSTEM_LOCALEDIR_NAME)
|
||||||
|
};
|
||||||
|
foreach (var path in search_paths) {
|
||||||
|
if (FileUtils.test(Path.build_filename(path, "en", "LC_MESSAGES", gettext_package + ".mo"), FileTest.IS_REGULAR)) {
|
||||||
|
debug(@"Found locale $(gettext_package).mo in $(path)");
|
||||||
|
return path;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return locale_dir ?? locale_install_dir;
|
}
|
||||||
|
|
||||||
|
return locale_install_dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string[] get_plugin_paths() {
|
public string[] get_plugin_paths() {
|
||||||
|
|
|
@ -4,6 +4,7 @@ int main(string[] args) {
|
||||||
GLib.Test.init(ref args);
|
GLib.Test.init(ref args);
|
||||||
GLib.Test.set_nonfatal_assertions();
|
GLib.Test.set_nonfatal_assertions();
|
||||||
TestSuite.get_root().add_suite(new WeakMapTest().get_suite());
|
TestSuite.get_root().add_suite(new WeakMapTest().get_suite());
|
||||||
|
TestSuite.get_root().add_suite(new JidTest().get_suite());
|
||||||
return GLib.Test.run();
|
return GLib.Test.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using Dino.Entities;
|
using Dino.Entities;
|
||||||
|
using Xmpp;
|
||||||
|
|
||||||
namespace Dino.Test {
|
namespace Dino.Test {
|
||||||
|
|
||||||
|
@ -12,27 +13,39 @@ class JidTest : Gee.TestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void test_parse() {
|
private void test_parse() {
|
||||||
|
try {
|
||||||
Jid jid = new Jid("user@example.com/res");
|
Jid jid = new Jid("user@example.com/res");
|
||||||
fail_if(jid.localpart != "user");
|
fail_if(jid.localpart != "user");
|
||||||
fail_if(jid.domainpart != "example.com");
|
fail_if(jid.domainpart != "example.com");
|
||||||
fail_if(jid.resourcepart != "res");
|
fail_if(jid.resourcepart != "res");
|
||||||
fail_if(jid.to_string() != "user@example.com/res");
|
fail_if(jid.to_string() != "user@example.com/res");
|
||||||
|
} catch (Error e) {
|
||||||
|
fail_if_reached(@"Throws $(e.message)");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void test_components() {
|
private void test_components() {
|
||||||
|
try {
|
||||||
Jid jid = new Jid.components("user", "example.com", "res");
|
Jid jid = new Jid.components("user", "example.com", "res");
|
||||||
fail_if(jid.localpart != "user");
|
fail_if(jid.localpart != "user");
|
||||||
fail_if(jid.domainpart != "example.com");
|
fail_if(jid.domainpart != "example.com");
|
||||||
fail_if(jid.resourcepart != "res");
|
fail_if(jid.resourcepart != "res");
|
||||||
fail_if(jid.to_string() != "user@example.com/res");
|
fail_if(jid.to_string() != "user@example.com/res");
|
||||||
|
} catch (Error e) {
|
||||||
|
fail_if_reached(@"Throws $(e.message)");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void test_with_res() {
|
private void test_with_res() {
|
||||||
Jid jid = new Jid.with_resource("user@example.com", "res");
|
try {
|
||||||
|
Jid jid = new Jid("user@example.com").with_resource("res");
|
||||||
fail_if(jid.localpart != "user");
|
fail_if(jid.localpart != "user");
|
||||||
fail_if(jid.domainpart != "example.com");
|
fail_if(jid.domainpart != "example.com");
|
||||||
fail_if(jid.resourcepart != "res");
|
fail_if(jid.resourcepart != "res");
|
||||||
fail_if(jid.to_string() != "user@example.com/res");
|
fail_if(jid.to_string() != "user@example.com/res");
|
||||||
|
} catch (Error e) {
|
||||||
|
fail_if_reached(@"Throws $(e.message)");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -49,6 +49,8 @@ set(RESOURCE_LIST
|
||||||
icons/scalable/status/dino-status-chat.svg
|
icons/scalable/status/dino-status-chat.svg
|
||||||
icons/scalable/status/dino-status-dnd.svg
|
icons/scalable/status/dino-status-dnd.svg
|
||||||
icons/scalable/status/dino-status-online.svg
|
icons/scalable/status/dino-status-online.svg
|
||||||
|
icons/scalable/status/dino-status-online-bright.svg
|
||||||
|
icons/scalable/status/dino-status-offline.svg
|
||||||
icons/scalable/status/dino-tick-symbolic.svg
|
icons/scalable/status/dino-tick-symbolic.svg
|
||||||
icons/scalable/status/dino-video-off-symbolic.svg
|
icons/scalable/status/dino-video-off-symbolic.svg
|
||||||
icons/scalable/status/dino-video-symbolic.svg
|
icons/scalable/status/dino-video-symbolic.svg
|
||||||
|
@ -67,6 +69,7 @@ set(RESOURCE_LIST
|
||||||
conversation_list_titlebar_csd.ui
|
conversation_list_titlebar_csd.ui
|
||||||
conversation_row.ui
|
conversation_row.ui
|
||||||
conversation_view.ui
|
conversation_view.ui
|
||||||
|
default_encryption_dialog.ui
|
||||||
file_default_widget.ui
|
file_default_widget.ui
|
||||||
file_send_overlay.ui
|
file_send_overlay.ui
|
||||||
global_search.ui
|
global_search.ui
|
||||||
|
@ -78,6 +81,7 @@ set(RESOURCE_LIST
|
||||||
conversation_content_view/view.ui
|
conversation_content_view/view.ui
|
||||||
manage_accounts/account_row.ui
|
manage_accounts/account_row.ui
|
||||||
manage_accounts/add_account_dialog.ui
|
manage_accounts/add_account_dialog.ui
|
||||||
|
manage_accounts/change_password_dialog.ui
|
||||||
manage_accounts/dialog.ui
|
manage_accounts/dialog.ui
|
||||||
menu_add.ui
|
menu_add.ui
|
||||||
menu_app.ui
|
menu_app.ui
|
||||||
|
@ -203,6 +207,7 @@ SOURCES
|
||||||
|
|
||||||
src/ui/contact_details/settings_provider.vala
|
src/ui/contact_details/settings_provider.vala
|
||||||
src/ui/contact_details/permissions_provider.vala
|
src/ui/contact_details/permissions_provider.vala
|
||||||
|
src/ui/contact_details/history_provider.vala
|
||||||
|
|
||||||
src/ui/conversation_details.vala
|
src/ui/conversation_details.vala
|
||||||
|
|
||||||
|
@ -217,6 +222,7 @@ SOURCES
|
||||||
|
|
||||||
src/ui/manage_accounts/account_row.vala
|
src/ui/manage_accounts/account_row.vala
|
||||||
src/ui/manage_accounts/add_account_dialog.vala
|
src/ui/manage_accounts/add_account_dialog.vala
|
||||||
|
src/ui/manage_accounts/change_password_dialog.vala
|
||||||
src/ui/manage_accounts/dialog.vala
|
src/ui/manage_accounts/dialog.vala
|
||||||
|
|
||||||
src/ui/occupant_menu/list.vala
|
src/ui/occupant_menu/list.vala
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
<object class="GtkButton" id="file_button">
|
<object class="GtkButton" id="file_button">
|
||||||
<property name="icon-name">mail-attachment-symbolic</property>
|
<property name="icon-name">mail-attachment-symbolic</property>
|
||||||
<property name="margin-top">2</property>
|
<property name="margin-top">2</property>
|
||||||
<property name="valign">start</property>
|
<property name="valign">center</property>
|
||||||
<style>
|
<style>
|
||||||
<class name="flat"/>
|
<class name="flat"/>
|
||||||
<class name="dino-chatinput-button"/>
|
<class name="dino-chatinput-button"/>
|
||||||
|
@ -54,7 +54,7 @@
|
||||||
<property name="icon-name">emoji-people-symbolic</property>
|
<property name="icon-name">emoji-people-symbolic</property>
|
||||||
<property name="has-frame">False</property>
|
<property name="has-frame">False</property>
|
||||||
<property name="margin-top">2</property>
|
<property name="margin-top">2</property>
|
||||||
<property name="valign">start</property>
|
<property name="valign">center</property>
|
||||||
<style>
|
<style>
|
||||||
<class name="flat"/>
|
<class name="flat"/>
|
||||||
<class name="dino-chatinput-button"/>
|
<class name="dino-chatinput-button"/>
|
||||||
|
@ -67,7 +67,21 @@
|
||||||
<property name="icon-name">changes-allow-symbolic</property>
|
<property name="icon-name">changes-allow-symbolic</property>
|
||||||
<property name="has-frame">False</property>
|
<property name="has-frame">False</property>
|
||||||
<property name="margin-top">2</property>
|
<property name="margin-top">2</property>
|
||||||
<property name="valign">start</property>
|
<property name="valign">center</property>
|
||||||
|
<style>
|
||||||
|
<class name="flat"/>
|
||||||
|
<class name="dino-chatinput-button"/>
|
||||||
|
<class name="image-button"/>
|
||||||
|
</style>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkButton" id="send_button">
|
||||||
|
<property name="icon-name">mail-send-symbolic</property>
|
||||||
|
<property name="has-frame">False</property>
|
||||||
|
<property name="margin-top">2</property>
|
||||||
|
<property name="valign">center</property>
|
||||||
|
<property name="sensitive">false</property>
|
||||||
<style>
|
<style>
|
||||||
<class name="flat"/>
|
<class name="flat"/>
|
||||||
<class name="dino-chatinput-button"/>
|
<class name="dino-chatinput-button"/>
|
||||||
|
|
|
@ -37,11 +37,6 @@
|
||||||
<property name="xalign">0</property>
|
<property name="xalign">0</property>
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
|
||||||
<object class="GtkRevealer" id="time_revealer">
|
|
||||||
<property name="transition-type">slide-right</property>
|
|
||||||
<property name="transition-duration">50</property>
|
|
||||||
<property name="reveal-child">True</property>
|
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkLabel" id="time_label">
|
<object class="GtkLabel" id="time_label">
|
||||||
<property name="hexpand">False</property>
|
<property name="hexpand">False</property>
|
||||||
|
@ -53,8 +48,6 @@
|
||||||
</child>
|
</child>
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
</object>
|
|
||||||
</child>
|
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkBox">
|
<object class="GtkBox">
|
||||||
<property name="valign">end</property>
|
<property name="valign">end</property>
|
||||||
|
@ -87,15 +80,10 @@
|
||||||
</attributes>
|
</attributes>
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
|
||||||
<object class="GtkRevealer" id="top_row_revealer">
|
|
||||||
<property name="transition-type">slide-right</property>
|
|
||||||
<property name="transition-duration">50</property>
|
|
||||||
<property name="reveal-child">True</property>
|
|
||||||
<property name="margin-start">15</property>
|
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkBox">
|
<object class="GtkBox">
|
||||||
<property name="orientation">horizontal</property>
|
<property name="orientation">horizontal</property>
|
||||||
|
<property name="margin-start">15</property>
|
||||||
<property name="spacing">6</property>
|
<property name="spacing">6</property>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkLabel" id="unread_count_label">
|
<object class="GtkLabel" id="unread_count_label">
|
||||||
|
@ -123,49 +111,6 @@
|
||||||
</child>
|
</child>
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
|
||||||
<object class="GtkBox">
|
|
||||||
<property name="orientation">vertical</property>
|
|
||||||
<child>
|
|
||||||
<object class="GtkBox">
|
|
||||||
<property name="vexpand">True</property>
|
|
||||||
</object>
|
|
||||||
</child>
|
|
||||||
<child>
|
|
||||||
<object class="GtkRevealer" id="xbutton_revealer">
|
|
||||||
<property name="transition-type">slide-left</property>
|
|
||||||
<property name="transition-duration">100</property>
|
|
||||||
<property name="reveal-child">False</property>
|
|
||||||
<child>
|
|
||||||
<object class="GtkButton" id="x_button">
|
|
||||||
<property name="width-request">27</property>
|
|
||||||
<property name="height-request">27</property>
|
|
||||||
<property name="vexpand">False</property>
|
|
||||||
<property name="margin-start">5</property>
|
|
||||||
<style>
|
|
||||||
<class name="conversation_list_row_xbutton"/>
|
|
||||||
<class name="circular"/>
|
|
||||||
<class name="flat"/>
|
|
||||||
</style>
|
|
||||||
<child>
|
|
||||||
<object class="GtkImage">
|
|
||||||
<property name="icon-name">window-close-symbolic</property>
|
|
||||||
<property name="icon-size">1</property>
|
|
||||||
</object>
|
|
||||||
</child>
|
|
||||||
</object>
|
|
||||||
</child>
|
|
||||||
</object>
|
|
||||||
</child>
|
|
||||||
<child>
|
|
||||||
<object class="GtkBox">
|
|
||||||
<property name="vexpand">True</property>
|
|
||||||
</object>
|
|
||||||
</child>
|
|
||||||
</object>
|
|
||||||
</child>
|
|
||||||
</object>
|
|
||||||
</child>
|
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
</template>
|
</template>
|
||||||
|
|
83
main/data/default_encryption_dialog.ui
Normal file
83
main/data/default_encryption_dialog.ui
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<interface>
|
||||||
|
<requires lib="gtk" version="4.0"/>
|
||||||
|
<object class="GtkDialog" id="dialog">
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="modal">True</property>
|
||||||
|
<property name="default_width">320</property>
|
||||||
|
<property name="default_height">260</property>
|
||||||
|
<property name="resizable">False</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkBox">
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="orientation">vertical</property>
|
||||||
|
<property name="margin-start">20</property>
|
||||||
|
<property name="margin-end">20</property>
|
||||||
|
<property name="margin-top">20</property>
|
||||||
|
<property name="margin-bottom">20</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkBox">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="orientation">vertical</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel" id="default_encryption_warning_label">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="label" translatable="yes">You are opening a new conversation without having set end-to-end encryption by default.
|
||||||
|
|
||||||
|
It is strongly recommended to enable it to prevent your messages from being read by third parties.
|
||||||
|
|
||||||
|
Please select an option to start this conversation with. Choosing one of the encryption methods will also set it as default in the global settings.
|
||||||
|
</property>
|
||||||
|
<property name="wrap">True</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkCheckButton" id="omemo">
|
||||||
|
<property name="label" translatable="yes">OMEMO (automatic setup)</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="receives_default">False</property>
|
||||||
|
<property name="active">False</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkCheckButton" id="openpgp">
|
||||||
|
<property name="label" translatable="yes">OpenPGP (external setup required)</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="receives_default">False</property>
|
||||||
|
<property name="active">False</property>
|
||||||
|
<property name="group">omemo</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkCheckButton" id="none">
|
||||||
|
<property name="label" translatable="yes">Unencrypted</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="receives_default">False</property>
|
||||||
|
<property name="active">False</property>
|
||||||
|
<property name="group">omemo</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkButton" id="accept_button">
|
||||||
|
<property name="label" translatable="yes">Apply</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="receives_default">True</property>
|
||||||
|
<property name="margin-top">20</property>
|
||||||
|
<style>
|
||||||
|
<class name="text-button"/>
|
||||||
|
<class name="suggested-action"/>
|
||||||
|
</style>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</interface>
|
|
@ -11,11 +11,13 @@
|
||||||
<file>conversation_content_view/item_metadata_header.ui</file>
|
<file>conversation_content_view/item_metadata_header.ui</file>
|
||||||
<file>conversation_content_view/view.ui</file>
|
<file>conversation_content_view/view.ui</file>
|
||||||
<file>conversation_details.ui</file>
|
<file>conversation_details.ui</file>
|
||||||
|
<file>conversation_details.css</file>
|
||||||
<file>conversation_item_widget.ui</file>
|
<file>conversation_item_widget.ui</file>
|
||||||
<file>conversation_list_titlebar.ui</file>
|
<file>conversation_list_titlebar.ui</file>
|
||||||
<file>conversation_list_titlebar_csd.ui</file>
|
<file>conversation_list_titlebar_csd.ui</file>
|
||||||
<file>conversation_row.ui</file>
|
<file>conversation_row.ui</file>
|
||||||
<file>conversation_view.ui</file>
|
<file>conversation_view.ui</file>
|
||||||
|
<file>default_encryption_dialog.ui</file>
|
||||||
<file>dino-conversation-list-placeholder-arrow.svg</file>
|
<file>dino-conversation-list-placeholder-arrow.svg</file>
|
||||||
<file>file_default_widget.ui</file>
|
<file>file_default_widget.ui</file>
|
||||||
<file>file_send_overlay.ui</file>
|
<file>file_send_overlay.ui</file>
|
||||||
|
@ -49,6 +51,8 @@
|
||||||
<file>icons/scalable/status/dino-status-chat.svg</file>
|
<file>icons/scalable/status/dino-status-chat.svg</file>
|
||||||
<file>icons/scalable/status/dino-status-dnd.svg</file>
|
<file>icons/scalable/status/dino-status-dnd.svg</file>
|
||||||
<file>icons/scalable/status/dino-status-online.svg</file>
|
<file>icons/scalable/status/dino-status-online.svg</file>
|
||||||
|
<file>icons/scalable/status/dino-status-online-bright.svg</file>
|
||||||
|
<file>icons/scalable/status/dino-status-offline.svg</file>
|
||||||
<file>icons/scalable/status/dino-tick-symbolic.svg</file>
|
<file>icons/scalable/status/dino-tick-symbolic.svg</file>
|
||||||
<file>icons/scalable/status/dino-video-off-symbolic.svg</file>
|
<file>icons/scalable/status/dino-video-off-symbolic.svg</file>
|
||||||
<file>icons/scalable/status/dino-video-symbolic.svg</file>
|
<file>icons/scalable/status/dino-video-symbolic.svg</file>
|
||||||
|
@ -58,6 +62,7 @@
|
||||||
<file>manage_accounts/account_row.ui</file>
|
<file>manage_accounts/account_row.ui</file>
|
||||||
<file>manage_accounts/add_account_dialog.ui</file>
|
<file>manage_accounts/add_account_dialog.ui</file>
|
||||||
<file>manage_accounts/dialog.ui</file>
|
<file>manage_accounts/dialog.ui</file>
|
||||||
|
<file>manage_accounts/change_password_dialog.ui</file>
|
||||||
<file>menu_add.ui</file>
|
<file>menu_add.ui</file>
|
||||||
<file>menu_app.ui</file>
|
<file>menu_app.ui</file>
|
||||||
<file>menu_conversation.ui</file>
|
<file>menu_conversation.ui</file>
|
||||||
|
|
11
main/data/icons/scalable/status/dino-status-offline.svg
Normal file
11
main/data/icons/scalable/status/dino-status-offline.svg
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<svg width="99.999997" height="99.999997" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" version="1.1">
|
||||||
|
|
||||||
|
<g class="layer">
|
||||||
|
<title>Layer 1</title>
|
||||||
|
<g id="svg_1">
|
||||||
|
<circle cx="50" cy="51" fill="#ff0000" fill-rule="evenodd" id="svg_2" r="50" stroke="#ff0000"/>
|
||||||
|
<path d="m20,51l60,0" fill="#ff0000" id="svg_3" stroke="#ff0000" stroke-linecap="round" stroke-width="15"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 444 B |
|
@ -0,0 +1,10 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<svg width="99.999997" height="99.999997" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" version="1.1">
|
||||||
|
|
||||||
|
<g class="layer">
|
||||||
|
<title>Layer 1</title>
|
||||||
|
<g id="svg_1">
|
||||||
|
<circle cx="50" cy="50" fill="#00ff00" fill-rule="evenodd" id="svg_2" r="50"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 316 B |
|
@ -1,6 +1,10 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0"?>
|
||||||
<svg width="28.222mm" height="28.222mm" version="1.1" viewBox="0 0 99.999997 99.999997" xmlns="http://www.w3.org/2000/svg">
|
<svg width="99.999997" height="99.999997" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" version="1.1">
|
||||||
<g transform="translate(-62.857 -678.08)">
|
|
||||||
<circle cx="112.86" cy="728.08" r="50" style="fill-rule:evenodd;fill:#81c784"/>
|
<g class="layer">
|
||||||
|
<title>Layer 1</title>
|
||||||
|
<g id="svg_1">
|
||||||
|
<circle cx="50" cy="50" fill="#00ff00" fill-rule="evenodd" id="svg_2" r="50"/>
|
||||||
|
</g>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
Before Width: | Height: | Size: 302 B After Width: | Height: | Size: 316 B |
|
@ -4,7 +4,7 @@
|
||||||
<launchable type="desktop-id">im.dino.Dino.desktop</launchable>
|
<launchable type="desktop-id">im.dino.Dino.desktop</launchable>
|
||||||
<metadata_license>CC0-1.0</metadata_license>
|
<metadata_license>CC0-1.0</metadata_license>
|
||||||
<project_license>GPL-3.0+</project_license>
|
<project_license>GPL-3.0+</project_license>
|
||||||
<name>Dino</name>
|
<name>Dino+</name>
|
||||||
<summary>Modern XMPP Chat Client</summary>
|
<summary>Modern XMPP Chat Client</summary>
|
||||||
<summary xml:lang="zh_TW">現代化的 XMPP 用戶端聊天軟件</summary>
|
<summary xml:lang="zh_TW">現代化的 XMPP 用戶端聊天軟件</summary>
|
||||||
<summary xml:lang="zh_CN">现代 XMPP 聊天客户端</summary>
|
<summary xml:lang="zh_CN">现代 XMPP 聊天客户端</summary>
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<launchable type="desktop-id">im.dino.Dino.desktop</launchable>
|
<launchable type="desktop-id">im.dino.Dino.desktop</launchable>
|
||||||
<metadata_license>CC0-1.0</metadata_license>
|
<metadata_license>CC0-1.0</metadata_license>
|
||||||
<project_license>GPL-3.0+</project_license>
|
<project_license>GPL-3.0+</project_license>
|
||||||
<name>Dino</name>
|
<name>Dino+</name>
|
||||||
<summary>Modern XMPP Chat Client</summary>
|
<summary>Modern XMPP Chat Client</summary>
|
||||||
<description>
|
<description>
|
||||||
<p>Dino is a modern open-source chat client for the desktop. It focuses on providing a clean and reliable Jabber/XMPP experience while having your privacy in mind.</p>
|
<p>Dino is a modern open-source chat client for the desktop. It focuses on providing a clean and reliable Jabber/XMPP experience while having your privacy in mind.</p>
|
||||||
|
|
158
main/data/manage_accounts/change_password_dialog.ui
Normal file
158
main/data/manage_accounts/change_password_dialog.ui
Normal file
|
@ -0,0 +1,158 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<interface>
|
||||||
|
<requires lib="gtk" version="4.0"/>
|
||||||
|
<template class="DinoUiChangePasswordDialog">
|
||||||
|
<property name="title" translatable="1">Change password</property>
|
||||||
|
<property name="valign">center</property>
|
||||||
|
<property name="modal">True</property>
|
||||||
|
<child internal-child="content_area">
|
||||||
|
<object class="GtkBox">
|
||||||
|
<child>
|
||||||
|
<object class="GtkGrid" id="info_grid">
|
||||||
|
<property name="orientation">vertical</property>
|
||||||
|
<property name="margin-start">20</property>
|
||||||
|
<property name="margin-end">20</property>
|
||||||
|
<property name="margin-top">20</property>
|
||||||
|
<property name="margin-bottom">20</property>
|
||||||
|
<property name="row-spacing">7</property>
|
||||||
|
<property name="column-spacing">10</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel">
|
||||||
|
<property name="label" translatable="1">Current password</property>
|
||||||
|
<property name="xalign">1</property>
|
||||||
|
<layout>
|
||||||
|
<property name="column">0</property>
|
||||||
|
<property name="row">0</property>
|
||||||
|
</layout>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkEntry" id="current_passwd_entry">
|
||||||
|
<property name="activates_default">1</property>
|
||||||
|
<property name="hexpand">1</property>
|
||||||
|
<property name="width_request">200</property>
|
||||||
|
<property name="visibility">False</property>
|
||||||
|
<layout>
|
||||||
|
<property name="column">1</property>
|
||||||
|
<property name="row">0</property>
|
||||||
|
</layout>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel">
|
||||||
|
<property name="label" translatable="1">New password</property>
|
||||||
|
<property name="xalign">1</property>
|
||||||
|
<layout>
|
||||||
|
<property name="column">0</property>
|
||||||
|
<property name="row">1</property>
|
||||||
|
</layout>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkEntry" id="new_passwd_entry">
|
||||||
|
<property name="activates_default">1</property>
|
||||||
|
<property name="hexpand">1</property>
|
||||||
|
<property name="width_request">200</property>
|
||||||
|
<property name="visibility">False</property>
|
||||||
|
<layout>
|
||||||
|
<property name="column">1</property>
|
||||||
|
<property name="row">1</property>
|
||||||
|
</layout>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel">
|
||||||
|
<property name="label" translatable="1">Confirm new password</property>
|
||||||
|
<property name="xalign">1</property>
|
||||||
|
<layout>
|
||||||
|
<property name="column">0</property>
|
||||||
|
<property name="row">2</property>
|
||||||
|
</layout>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkEntry" id="confirm_new_passwd_entry">
|
||||||
|
<property name="activates_default">1</property>
|
||||||
|
<property name="hexpand">1</property>
|
||||||
|
<property name="width_request">200</property>
|
||||||
|
<property name="visibility">False</property>
|
||||||
|
<layout>
|
||||||
|
<property name="column">1</property>
|
||||||
|
<property name="row">2</property>
|
||||||
|
</layout>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel" id="change_password_error_label">
|
||||||
|
<!-- property name="xalign">0</property -->
|
||||||
|
<property name="halign">center</property>
|
||||||
|
<property name="hexpand">True</property>
|
||||||
|
<property name="margin-top">7</property>
|
||||||
|
<attributes>
|
||||||
|
<attribute name="scale" value="0.9"></attribute>
|
||||||
|
</attributes>
|
||||||
|
<layout>
|
||||||
|
<property name="column">0</property>
|
||||||
|
<property name="row">3</property>
|
||||||
|
<property name="column-span">2</property>
|
||||||
|
</layout>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkButton" id="cancel_button">
|
||||||
|
<property name="label" translatable="1">Cancel</property>
|
||||||
|
<layout>
|
||||||
|
<property name="column">0</property>
|
||||||
|
<property name="row">4</property>
|
||||||
|
</layout>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkButton" id="change_password_button">
|
||||||
|
<property name="halign">end</property>
|
||||||
|
<property name="hexpand">True</property>
|
||||||
|
<property name="sensitive">0</property>
|
||||||
|
<layout>
|
||||||
|
<property name="column">1</property>
|
||||||
|
<property name="row">4</property>
|
||||||
|
</layout>
|
||||||
|
<style>
|
||||||
|
<class name="text-button"/>
|
||||||
|
<class name="suggested-action"/>
|
||||||
|
</style>
|
||||||
|
<child>
|
||||||
|
<object class="GtkStack" id="change_password_stack">
|
||||||
|
<child>
|
||||||
|
<object class="GtkStackPage">
|
||||||
|
<property name="name">label</property>
|
||||||
|
<property name="child">
|
||||||
|
<object class="GtkLabel" >
|
||||||
|
<property name="label" translatable="1">Change password</property>
|
||||||
|
</object>
|
||||||
|
</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkStackPage">
|
||||||
|
<property name="name">spinner</property>
|
||||||
|
<property name="child">
|
||||||
|
<object class="GtkSpinner">
|
||||||
|
<property name="spinning">True</property>
|
||||||
|
</object>
|
||||||
|
</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<action-widgets>
|
||||||
|
<action-widget response="cancel">cancel_button</action-widget>
|
||||||
|
<action-widget response="ok" default="true">change_password_button</action-widget>
|
||||||
|
</action-widgets>
|
||||||
|
</template>
|
||||||
|
</interface>
|
|
@ -165,7 +165,17 @@
|
||||||
<layout>
|
<layout>
|
||||||
<property name="column">1</property>
|
<property name="column">1</property>
|
||||||
<property name="row">2</property>
|
<property name="row">2</property>
|
||||||
<property name="column-span">2</property>
|
<property name="column-span">1</property>
|
||||||
|
</layout>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkButton" id="password_change_btn">
|
||||||
|
<property name="label">⚙️</property>
|
||||||
|
<layout>
|
||||||
|
<property name="column">2</property>
|
||||||
|
<property name="row">2</property>
|
||||||
|
<property name="column-span">1</property>
|
||||||
</layout>
|
</layout>
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<property name="margin-start">7</property>
|
<property name="margin-start">7</property>
|
||||||
<property name="margin-bottom">3</property>
|
<property name="margin-bottom">3</property>
|
||||||
<property name="margin-end">7</property>
|
<property name="margin-end">7</property>
|
||||||
<property name="column-spacing">10</property>
|
<property name="column-spacing">5</property>
|
||||||
<child>
|
<child>
|
||||||
<object class="DinoUiAvatarPicture" id="picture">
|
<object class="DinoUiAvatarPicture" id="picture">
|
||||||
<property name="height-request">30</property>
|
<property name="height-request">30</property>
|
||||||
|
@ -15,7 +15,8 @@
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkLabel" id="name_label">
|
<object class="GtkLabel" id="name_label">
|
||||||
<property name="max_width_chars">1</property>
|
<property name="width-chars">20</property>
|
||||||
|
<property name="max-width-chars">40</property>
|
||||||
<property name="ellipsize">end</property>
|
<property name="ellipsize">end</property>
|
||||||
<property name="hexpand">1</property>
|
<property name="hexpand">1</property>
|
||||||
<property name="xalign">0</property>
|
<property name="xalign">0</property>
|
||||||
|
|
|
@ -7,6 +7,49 @@
|
||||||
<property name="search-enabled">False</property>
|
<property name="search-enabled">False</property>
|
||||||
<child>
|
<child>
|
||||||
<object class="AdwPreferencesPage">
|
<object class="AdwPreferencesPage">
|
||||||
|
<child>
|
||||||
|
<object class="AdwPreferencesGroup">
|
||||||
|
<child>
|
||||||
|
<object class="AdwActionRow">
|
||||||
|
<property name="title" translatable="yes">Default encryption for 1-on-1 chats</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkBox" id="default_encryption_box">
|
||||||
|
<child>
|
||||||
|
<object class="GtkCheckButton" id="encryption_radio_undecided">
|
||||||
|
<property name="label" translatable="yes">Ask</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="receives_default">False</property>
|
||||||
|
<property name="active">False</property>
|
||||||
|
<property name="group">encryption_radio_undecided</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkCheckButton" id="encryption_radio_omemo">
|
||||||
|
<property name="label" translatable="yes">OMEMO</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="receives_default">False</property>
|
||||||
|
<property name="active">False</property>
|
||||||
|
<property name="group">encryption_radio_undecided</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkCheckButton" id="encryption_radio_openpgp">
|
||||||
|
<property name="label" translatable="yes">OpenPGP</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="receives_default">False</property>
|
||||||
|
<property name="active">False</property>
|
||||||
|
<property name="group">encryption_radio_undecided</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<object class="AdwPreferencesGroup">
|
<object class="AdwPreferencesGroup">
|
||||||
<child>
|
<child>
|
||||||
|
@ -68,6 +111,51 @@
|
||||||
</child>
|
</child>
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="AdwPreferencesGroup">
|
||||||
|
<child>
|
||||||
|
<object class="AdwActionRow">
|
||||||
|
<property name="title" translatable="yes">_Display send button</property>
|
||||||
|
<property name="use-underline">True</property>
|
||||||
|
<property name="activatable-widget">send_button_switch</property>
|
||||||
|
<child type="suffix">
|
||||||
|
<object class="GtkSwitch" id="send_button_switch">
|
||||||
|
<property name="valign">center</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="AdwActionRow">
|
||||||
|
<property name="title" translatable="yes">_Use Enter key to start a new line</property>
|
||||||
|
<property name="subtitle" translatable="yes">If disabled, use Shift+Enter to start a new line</property>
|
||||||
|
<property name="use-underline">True</property>
|
||||||
|
<property name="activatable-widget">enter_newline_switch</property>
|
||||||
|
<child type="suffix">
|
||||||
|
<object class="GtkSwitch" id="enter_newline_switch">
|
||||||
|
<property name="valign">center</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="AdwPreferencesGroup">
|
||||||
|
<child>
|
||||||
|
<object class="AdwActionRow">
|
||||||
|
<property name="title" translatable="yes">_Dark theme</property>
|
||||||
|
<property name="use-underline">True</property>
|
||||||
|
<property name="activatable-widget">dark_theme</property>
|
||||||
|
<child type="suffix">
|
||||||
|
<object class="GtkSwitch" id="dark_theme">
|
||||||
|
<property name="valign">center</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -49,7 +49,11 @@ window.dino-main .dino-conversation .message-box.highlight:not(.highlight-once)
|
||||||
}
|
}
|
||||||
|
|
||||||
window.dino-main .dino-conversation .message-box {
|
window.dino-main .dino-conversation .message-box {
|
||||||
padding: 6px 15px 6px 15px;
|
padding: 3px 15px 3px 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
window.dino-main .dino-conversation .has-skeleton {
|
||||||
|
margin-top: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
window.dino-main .dino-conversation .message-box:not(.has-skeleton) {
|
window.dino-main .dino-conversation .message-box:not(.has-skeleton) {
|
||||||
|
|
|
@ -39,6 +39,7 @@ sources = files(
|
||||||
'src/ui/chat_input/view.vala',
|
'src/ui/chat_input/view.vala',
|
||||||
'src/ui/contact_details/permissions_provider.vala',
|
'src/ui/contact_details/permissions_provider.vala',
|
||||||
'src/ui/contact_details/settings_provider.vala',
|
'src/ui/contact_details/settings_provider.vala',
|
||||||
|
'src/ui/contact_details/history_provider.vala',
|
||||||
'src/ui/conversation_content_view/call_widget.vala',
|
'src/ui/conversation_content_view/call_widget.vala',
|
||||||
'src/ui/conversation_content_view/chat_state_populator.vala',
|
'src/ui/conversation_content_view/chat_state_populator.vala',
|
||||||
'src/ui/conversation_content_view/content_populator.vala',
|
'src/ui/conversation_content_view/content_populator.vala',
|
||||||
|
@ -71,6 +72,7 @@ sources = files(
|
||||||
'src/ui/main_window_controller.vala',
|
'src/ui/main_window_controller.vala',
|
||||||
'src/ui/manage_accounts/account_row.vala',
|
'src/ui/manage_accounts/account_row.vala',
|
||||||
'src/ui/manage_accounts/add_account_dialog.vala',
|
'src/ui/manage_accounts/add_account_dialog.vala',
|
||||||
|
'src/ui/manage_accounts/change_password_dialog.vala',
|
||||||
'src/ui/manage_accounts/dialog.vala',
|
'src/ui/manage_accounts/dialog.vala',
|
||||||
'src/ui/notifier_freedesktop.vala',
|
'src/ui/notifier_freedesktop.vala',
|
||||||
'src/ui/notifier_gnotifications.vala',
|
'src/ui/notifier_gnotifications.vala',
|
||||||
|
@ -102,6 +104,8 @@ sources += gnome.compile_resources(
|
||||||
c_args = [
|
c_args = [
|
||||||
'-DG_LOG_DOMAIN="dino"',
|
'-DG_LOG_DOMAIN="dino"',
|
||||||
'-DGETTEXT_PACKAGE="dino"',
|
'-DGETTEXT_PACKAGE="dino"',
|
||||||
|
'-D_POSIX_C_SOURCE=1',
|
||||||
|
'-D_FILE_OFFSET_BITS=64',
|
||||||
'-DLOCALE_INSTALL_DIR="@0@"'.format(get_option('prefix') / get_option('localedir')),
|
'-DLOCALE_INSTALL_DIR="@0@"'.format(get_option('prefix') / get_option('localedir')),
|
||||||
]
|
]
|
||||||
vala_args = [
|
vala_args = [
|
||||||
|
@ -116,7 +120,15 @@ endif
|
||||||
if dep_gtk4.version() == 'unknown' or dep_gtk4.version().version_compare('>=4.8')
|
if dep_gtk4.version() == 'unknown' or dep_gtk4.version().version_compare('>=4.8')
|
||||||
vala_args += ['-D', 'GTK_4_8']
|
vala_args += ['-D', 'GTK_4_8']
|
||||||
endif
|
endif
|
||||||
exe_dino = executable('dino', sources, c_args: c_args, vala_args: vala_args, dependencies: dependencies, install: true)
|
|
||||||
|
link_args = []
|
||||||
|
if host_machine.system() == 'windows'
|
||||||
|
link_args += ['-Wl,--export-all-symbols']
|
||||||
|
windows = import('windows')
|
||||||
|
sources += windows.compile_resources('dino-info.rc')
|
||||||
|
endif
|
||||||
|
|
||||||
|
exe_dino = executable('dino', sources, c_args: c_args, vala_args: vala_args, dependencies: dependencies, install: true, link_args: link_args, win_subsystem: 'windows')
|
||||||
|
|
||||||
install_data('data/icons/scalable/apps/im.dino.Dino-symbolic.svg', install_dir: get_option('datadir') / 'hicolor/symbolic/apps')
|
install_data('data/icons/scalable/apps/im.dino.Dino-symbolic.svg', install_dir: get_option('datadir') / 'hicolor/symbolic/apps')
|
||||||
install_data('data/icons/scalable/apps/im.dino.Dino.svg', install_dir: get_option('datadir') / 'hicolor/scalable/apps')
|
install_data('data/icons/scalable/apps/im.dino.Dino.svg', install_dir: get_option('datadir') / 'hicolor/scalable/apps')
|
||||||
|
|
|
@ -1176,6 +1176,24 @@ msgstr "لقد أعددت كل شيء!"
|
||||||
msgid "Finish"
|
msgid "Finish"
|
||||||
msgstr "أنهي"
|
msgstr "أنهي"
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :5
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :103
|
||||||
|
msgid "Change password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :21
|
||||||
|
msgid "Current password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :43
|
||||||
|
msgid "New password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :65
|
||||||
|
msgid "Confirm new password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
|
||||||
#~ msgid "Click here to start a conversation or join a channel."
|
#~ msgid "Click here to start a conversation or join a channel."
|
||||||
#~ msgstr "اضغط هنا لبداية المحادثة أو للإنضمام إلى قناة."
|
#~ msgstr "اضغط هنا لبداية المحادثة أو للإنضمام إلى قناة."
|
||||||
|
|
||||||
|
|
|
@ -1163,6 +1163,24 @@ msgstr "Tot llest!"
|
||||||
msgid "Finish"
|
msgid "Finish"
|
||||||
msgstr "Finalitza"
|
msgstr "Finalitza"
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :5
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :103
|
||||||
|
msgid "Change password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :21
|
||||||
|
msgid "Current password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :43
|
||||||
|
msgid "New password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :65
|
||||||
|
msgid "Confirm new password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
|
||||||
#~ msgid "Click here to start a conversation or join a channel."
|
#~ msgid "Click here to start a conversation or join a channel."
|
||||||
#~ msgstr "Feu clic aquí per a començar una conversa o unir-vos a un canal."
|
#~ msgstr "Feu clic aquí per a començar una conversa o unir-vos a un canal."
|
||||||
|
|
||||||
|
|
|
@ -1166,5 +1166,22 @@ msgstr "Vše připraveno!"
|
||||||
msgid "Finish"
|
msgid "Finish"
|
||||||
msgstr "Dokončit"
|
msgstr "Dokončit"
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :5
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :103
|
||||||
|
msgid "Change password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :21
|
||||||
|
msgid "Current password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :43
|
||||||
|
msgid "New password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :65
|
||||||
|
msgid "Confirm new password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#~ msgid "Click here to start a conversation or join a channel."
|
#~ msgid "Click here to start a conversation or join a channel."
|
||||||
#~ msgstr "Kliknutím sem zahájíte konverzaci nebo se připojíte ke kanálu."
|
#~ msgstr "Kliknutím sem zahájíte konverzaci nebo se připojíte ke kanálu."
|
||||||
|
|
|
@ -1153,3 +1153,20 @@ msgstr ""
|
||||||
#: main/data/manage_accounts/add_account_dialog.ui:506
|
#: main/data/manage_accounts/add_account_dialog.ui:506
|
||||||
msgid "Finish"
|
msgid "Finish"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :5
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :103
|
||||||
|
msgid "Change password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :21
|
||||||
|
msgid "Current password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :43
|
||||||
|
msgid "New password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :65
|
||||||
|
msgid "Confirm new password"
|
||||||
|
msgstr ""
|
||||||
|
|
|
@ -1161,6 +1161,23 @@ msgstr "Fertig!"
|
||||||
msgid "Finish"
|
msgid "Finish"
|
||||||
msgstr "Fertig"
|
msgstr "Fertig"
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :5
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :103
|
||||||
|
msgid "Change password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :21
|
||||||
|
msgid "Current password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :43
|
||||||
|
msgid "New password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :65
|
||||||
|
msgid "Confirm new password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#~ msgid "Click here to start a conversation or join a channel."
|
#~ msgid "Click here to start a conversation or join a channel."
|
||||||
#~ msgstr ""
|
#~ msgstr ""
|
||||||
#~ "Klicke hier, um eine Unterhaltung zu starten oder einem Kanal beizutreten."
|
#~ "Klicke hier, um eine Unterhaltung zu starten oder einem Kanal beizutreten."
|
||||||
|
|
|
@ -1154,3 +1154,20 @@ msgstr ""
|
||||||
#: main/data/manage_accounts/add_account_dialog.ui:506
|
#: main/data/manage_accounts/add_account_dialog.ui:506
|
||||||
msgid "Finish"
|
msgid "Finish"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :5
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :103
|
||||||
|
msgid "Change password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :21
|
||||||
|
msgid "Current password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :43
|
||||||
|
msgid "New password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :65
|
||||||
|
msgid "Confirm new password"
|
||||||
|
msgstr ""
|
||||||
|
|
|
@ -1169,6 +1169,23 @@ msgstr "Όλα έτοιμα!"
|
||||||
msgid "Finish"
|
msgid "Finish"
|
||||||
msgstr "Ολοκλήρωση"
|
msgstr "Ολοκλήρωση"
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :5
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :103
|
||||||
|
msgid "Change password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :21
|
||||||
|
msgid "Current password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :43
|
||||||
|
msgid "New password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :65
|
||||||
|
msgid "Confirm new password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#~ msgid "Click here to start a conversation or join a channel."
|
#~ msgid "Click here to start a conversation or join a channel."
|
||||||
#~ msgstr ""
|
#~ msgstr ""
|
||||||
#~ "Κάντε κλικ εδώ για να ξεκινήσετε μια συνομιλία ή να εισέλθετε σε ένα "
|
#~ "Κάντε κλικ εδώ για να ξεκινήσετε μια συνομιλία ή να εισέλθετε σε ένα "
|
||||||
|
|
|
@ -533,12 +533,10 @@ msgid "Local Settings"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: main/src/ui/contact_details/settings_provider.vala:28
|
#: main/src/ui/contact_details/settings_provider.vala:28
|
||||||
#: main/data/settings_dialog.ui:23
|
|
||||||
msgid "Send typing notifications"
|
msgid "Send typing notifications"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: main/src/ui/contact_details/settings_provider.vala:33
|
#: main/src/ui/contact_details/settings_provider.vala:33
|
||||||
#: main/data/settings_dialog.ui:32
|
|
||||||
msgid "Send read receipts"
|
msgid "Send read receipts"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1012,16 +1010,48 @@ msgstr ""
|
||||||
msgid "Add Contact"
|
msgid "Add Contact"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: main/data/settings_dialog.ui:41
|
#: main/data/settings_dialog.ui:14
|
||||||
|
msgid "Default encryption for 1-on-1 chats"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/data/settings_dialog.ui:19
|
||||||
|
msgid "Ask"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/data/settings_dialog.ui:57
|
||||||
|
msgid "Send _Typing Notifications"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/data/settings_dialog.ui:85
|
||||||
|
msgid "_Notifications"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/data/settings_dialog.ui:69
|
||||||
|
msgid "Send _Read Receipts"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/data/settings_dialog.ui:86
|
||||||
msgid "Notify when a new message arrives"
|
msgid "Notify when a new message arrives"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: main/data/settings_dialog.ui:50
|
#: main/data/settings_dialog.ui:102
|
||||||
msgid "Convert smileys to emojis"
|
msgid "_Convert Smileys to Emoji"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: main/data/settings_dialog.ui:59
|
#: main/data/settings_dialog.ui:118
|
||||||
msgid "Check spelling"
|
msgid "_Display send button"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/data/settings_dialog.ui:130
|
||||||
|
msgid "_Use Enter key to start a new line"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/data/settings_dialog.ui:131
|
||||||
|
msgid "If disabled, use Shift+Enter to start a new line"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/data/settings_dialog.ui:147
|
||||||
|
msgid "_Dark theme"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: main/data/im.dino.Dino.appdata.xml.in:7
|
#: main/data/im.dino.Dino.appdata.xml.in:7
|
||||||
|
@ -1144,3 +1174,20 @@ msgstr ""
|
||||||
#: main/data/manage_accounts/add_account_dialog.ui:506
|
#: main/data/manage_accounts/add_account_dialog.ui:506
|
||||||
msgid "Finish"
|
msgid "Finish"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :5
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :103
|
||||||
|
msgid "Change password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :21
|
||||||
|
msgid "Current password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :43
|
||||||
|
msgid "New password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :65
|
||||||
|
msgid "Confirm new password"
|
||||||
|
msgstr ""
|
||||||
|
|
|
@ -1162,6 +1162,24 @@ msgstr "Ĉio pretas!"
|
||||||
msgid "Finish"
|
msgid "Finish"
|
||||||
msgstr "Fini"
|
msgstr "Fini"
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :5
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :103
|
||||||
|
msgid "Change password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :21
|
||||||
|
msgid "Current password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :43
|
||||||
|
msgid "New password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :65
|
||||||
|
msgid "Confirm new password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
|
||||||
#~ msgid "Click here to start a conversation or join a channel."
|
#~ msgid "Click here to start a conversation or join a channel."
|
||||||
#~ msgstr "Alklaku ĉi tie por komenci konversacion aŭ aliĝi al kanalo."
|
#~ msgstr "Alklaku ĉi tie por komenci konversacion aŭ aliĝi al kanalo."
|
||||||
|
|
||||||
|
|
|
@ -1166,6 +1166,23 @@ msgstr "¡Todo listo!"
|
||||||
msgid "Finish"
|
msgid "Finish"
|
||||||
msgstr "Finalizado"
|
msgstr "Finalizado"
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :5
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :103
|
||||||
|
msgid "Change password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :21
|
||||||
|
msgid "Current password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :43
|
||||||
|
msgid "New password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :65
|
||||||
|
msgid "Confirm new password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#~ msgid "Click here to start a conversation or join a channel."
|
#~ msgid "Click here to start a conversation or join a channel."
|
||||||
#~ msgstr ""
|
#~ msgstr ""
|
||||||
#~ "Pulsar aquí para iniciar una conversación o unirse a un conversación en "
|
#~ "Pulsar aquí para iniciar una conversación o unirse a un conversación en "
|
||||||
|
|
|
@ -1165,6 +1165,23 @@ msgstr "Guztia ezarri da!"
|
||||||
msgid "Finish"
|
msgid "Finish"
|
||||||
msgstr "Amaitu"
|
msgstr "Amaitu"
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :5
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :103
|
||||||
|
msgid "Change password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :21
|
||||||
|
msgid "Current password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :43
|
||||||
|
msgid "New password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :65
|
||||||
|
msgid "Confirm new password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#~ msgid "Click here to start a conversation or join a channel."
|
#~ msgid "Click here to start a conversation or join a channel."
|
||||||
#~ msgstr ""
|
#~ msgstr ""
|
||||||
#~ "Klikatu hemen elkarrizketa berri bat hasi edo kanal batean sartzeko."
|
#~ "Klikatu hemen elkarrizketa berri bat hasi edo kanal batean sartzeko."
|
||||||
|
|
|
@ -1161,6 +1161,23 @@ msgstr "همه تنظیم شده!"
|
||||||
msgid "Finish"
|
msgid "Finish"
|
||||||
msgstr "اتمام"
|
msgstr "اتمام"
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :5
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :103
|
||||||
|
msgid "Change password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :21
|
||||||
|
msgid "Current password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :43
|
||||||
|
msgid "New password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :65
|
||||||
|
msgid "Confirm new password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#~ msgid "Click here to start a conversation or join a channel."
|
#~ msgid "Click here to start a conversation or join a channel."
|
||||||
#~ msgstr "برای شروع گفتگو یا پیوستن به کانال اینجا کلیک کنید."
|
#~ msgstr "برای شروع گفتگو یا پیوستن به کانال اینجا کلیک کنید."
|
||||||
|
|
||||||
|
|
|
@ -1164,6 +1164,23 @@ msgstr ""
|
||||||
msgid "Finish"
|
msgid "Finish"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :5
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :103
|
||||||
|
msgid "Change password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :21
|
||||||
|
msgid "Current password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :43
|
||||||
|
msgid "New password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :65
|
||||||
|
msgid "Confirm new password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#~ msgid "No active conversations"
|
#~ msgid "No active conversations"
|
||||||
#~ msgstr "Ei aktiivisia keskusteluja"
|
#~ msgstr "Ei aktiivisia keskusteluja"
|
||||||
|
|
||||||
|
|
|
@ -1166,6 +1166,23 @@ msgstr "Tout est prêt !"
|
||||||
msgid "Finish"
|
msgid "Finish"
|
||||||
msgstr "Terminer"
|
msgstr "Terminer"
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :5
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :103
|
||||||
|
msgid "Change password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :21
|
||||||
|
msgid "Current password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :43
|
||||||
|
msgid "New password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :65
|
||||||
|
msgid "Confirm new password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#~ msgid "Click here to start a conversation or join a channel."
|
#~ msgid "Click here to start a conversation or join a channel."
|
||||||
#~ msgstr "Cliquez ici pour commencer une discussion ou rejoindre un salon."
|
#~ msgstr "Cliquez ici pour commencer une discussion ou rejoindre un salon."
|
||||||
|
|
||||||
|
|
|
@ -1166,6 +1166,23 @@ msgstr "Todo feito!"
|
||||||
msgid "Finish"
|
msgid "Finish"
|
||||||
msgstr "Rematar"
|
msgstr "Rematar"
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :5
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :103
|
||||||
|
msgid "Change password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :21
|
||||||
|
msgid "Current password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :43
|
||||||
|
msgid "New password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :65
|
||||||
|
msgid "Confirm new password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#~ msgid "Click here to start a conversation or join a channel."
|
#~ msgid "Click here to start a conversation or join a channel."
|
||||||
#~ msgstr "Preme aquí para iniciar unha conversa ou unirte a unha canle."
|
#~ msgstr "Preme aquí para iniciar unha conversa ou unirte a unha canle."
|
||||||
|
|
||||||
|
|
|
@ -1169,6 +1169,23 @@ msgstr "Minden készen áll!"
|
||||||
msgid "Finish"
|
msgid "Finish"
|
||||||
msgstr "Befejezés"
|
msgstr "Befejezés"
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :5
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :103
|
||||||
|
msgid "Change password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :21
|
||||||
|
msgid "Current password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :43
|
||||||
|
msgid "New password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :65
|
||||||
|
msgid "Confirm new password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#~ msgid "Click here to start a conversation or join a channel."
|
#~ msgid "Click here to start a conversation or join a channel."
|
||||||
#~ msgstr ""
|
#~ msgstr ""
|
||||||
#~ "Kattintson ide egy beszélgetés indításához vagy egy csatornához való "
|
#~ "Kattintson ide egy beszélgetés indításához vagy egy csatornához való "
|
||||||
|
|
|
@ -1157,5 +1157,22 @@ msgstr "Selesai!"
|
||||||
msgid "Finish"
|
msgid "Finish"
|
||||||
msgstr "Selesai"
|
msgstr "Selesai"
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :5
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :103
|
||||||
|
msgid "Change password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :21
|
||||||
|
msgid "Current password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :43
|
||||||
|
msgid "New password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :65
|
||||||
|
msgid "Confirm new password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#~ msgid "Click here to start a conversation or join a channel."
|
#~ msgid "Click here to start a conversation or join a channel."
|
||||||
#~ msgstr "Klik untuk memulai percakapan atau bergabung dengan channel."
|
#~ msgstr "Klik untuk memulai percakapan atau bergabung dengan channel."
|
||||||
|
|
|
@ -1161,6 +1161,23 @@ msgstr "Omni es pret!"
|
||||||
msgid "Finish"
|
msgid "Finish"
|
||||||
msgstr "Finir"
|
msgstr "Finir"
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :5
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :103
|
||||||
|
msgid "Change password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :21
|
||||||
|
msgid "Current password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :43
|
||||||
|
msgid "New password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :65
|
||||||
|
msgid "Confirm new password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#~ msgid "Click here to start a conversation or join a channel."
|
#~ msgid "Click here to start a conversation or join a channel."
|
||||||
#~ msgstr ""
|
#~ msgstr ""
|
||||||
#~ "Fa un clic ti-ci por iniciar un conversation o adherer a un channel."
|
#~ "Fa un clic ti-ci por iniciar un conversation o adherer a un channel."
|
||||||
|
|
|
@ -1161,5 +1161,22 @@ msgstr "Allt klárt!"
|
||||||
msgid "Finish"
|
msgid "Finish"
|
||||||
msgstr "Loka"
|
msgstr "Loka"
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :5
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :103
|
||||||
|
msgid "Change password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :21
|
||||||
|
msgid "Current password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :43
|
||||||
|
msgid "New password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :65
|
||||||
|
msgid "Confirm new password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#~ msgid "Click here to start a conversation or join a channel."
|
#~ msgid "Click here to start a conversation or join a channel."
|
||||||
#~ msgstr "Smelltu hér til að hefja samtal eða taka þátt í rás."
|
#~ msgstr "Smelltu hér til að hefja samtal eða taka þátt í rás."
|
||||||
|
|
|
@ -1165,6 +1165,23 @@ msgstr "Tutto pronto!"
|
||||||
msgid "Finish"
|
msgid "Finish"
|
||||||
msgstr "Fine"
|
msgstr "Fine"
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :5
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :103
|
||||||
|
msgid "Change password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :21
|
||||||
|
msgid "Current password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :43
|
||||||
|
msgid "New password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :65
|
||||||
|
msgid "Confirm new password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#~ msgid "Click here to start a conversation or join a channel."
|
#~ msgid "Click here to start a conversation or join a channel."
|
||||||
#~ msgstr ""
|
#~ msgstr ""
|
||||||
#~ "Fai clic qui per iniziare una conversazione o per entrare in un canale."
|
#~ "Fai clic qui per iniziare una conversazione o per entrare in un canale."
|
||||||
|
|
|
@ -1158,6 +1158,23 @@ msgstr "すべてのセットアップが完了しました!"
|
||||||
msgid "Finish"
|
msgid "Finish"
|
||||||
msgstr "完了"
|
msgstr "完了"
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :5
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :103
|
||||||
|
msgid "Change password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :21
|
||||||
|
msgid "Current password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :43
|
||||||
|
msgid "New password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :65
|
||||||
|
msgid "Confirm new password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#~ msgid "Click here to start a conversation or join a channel."
|
#~ msgid "Click here to start a conversation or join a channel."
|
||||||
#~ msgstr ""
|
#~ msgstr ""
|
||||||
#~ "トークを始めたりトークルームに参加したりするには、ここをクリックしてくださ"
|
#~ "トークを始めたりトークルームに参加したりするには、ここをクリックしてくださ"
|
||||||
|
|
|
@ -1153,3 +1153,20 @@ msgstr ""
|
||||||
#: main/data/manage_accounts/add_account_dialog.ui:506
|
#: main/data/manage_accounts/add_account_dialog.ui:506
|
||||||
msgid "Finish"
|
msgid "Finish"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :5
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :103
|
||||||
|
msgid "Change password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :21
|
||||||
|
msgid "Current password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :43
|
||||||
|
msgid "New password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :65
|
||||||
|
msgid "Confirm new password"
|
||||||
|
msgstr ""
|
||||||
|
|
|
@ -1166,5 +1166,22 @@ msgstr "모든 설정이 끝났습니다!"
|
||||||
msgid "Finish"
|
msgid "Finish"
|
||||||
msgstr "완료"
|
msgstr "완료"
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :5
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :103
|
||||||
|
msgid "Change password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :21
|
||||||
|
msgid "Current password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :43
|
||||||
|
msgid "New password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :65
|
||||||
|
msgid "Confirm new password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#~ msgid "Click here to start a conversation or join a channel."
|
#~ msgid "Click here to start a conversation or join a channel."
|
||||||
#~ msgstr "대화를 시작하거나 채널에 들어가려면 여기를 누르세요."
|
#~ msgstr "대화를 시작하거나 채널에 들어가려면 여기를 누르세요."
|
||||||
|
|
|
@ -1157,6 +1157,23 @@ msgstr "Alles ageriicht!"
|
||||||
msgid "Finish"
|
msgid "Finish"
|
||||||
msgstr "Ofschléissen"
|
msgstr "Ofschléissen"
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :5
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :103
|
||||||
|
msgid "Change password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :21
|
||||||
|
msgid "Current password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :43
|
||||||
|
msgid "New password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :65
|
||||||
|
msgid "Confirm new password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#~ msgid "Click here to start a conversation or join a channel."
|
#~ msgid "Click here to start a conversation or join a channel."
|
||||||
#~ msgstr ""
|
#~ msgstr ""
|
||||||
#~ "Klick hei fir eng Konversatioun ze starten oder engem Channel "
|
#~ "Klick hei fir eng Konversatioun ze starten oder engem Channel "
|
||||||
|
|
|
@ -1169,6 +1169,23 @@ msgstr "Viskas nustatyta!"
|
||||||
msgid "Finish"
|
msgid "Finish"
|
||||||
msgstr "Užbaigti"
|
msgstr "Užbaigti"
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :5
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :103
|
||||||
|
msgid "Change password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :21
|
||||||
|
msgid "Current password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :43
|
||||||
|
msgid "New password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :65
|
||||||
|
msgid "Confirm new password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#~ msgid "Click here to start a conversation or join a channel."
|
#~ msgid "Click here to start a conversation or join a channel."
|
||||||
#~ msgstr ""
|
#~ msgstr ""
|
||||||
#~ "Spustelėkite čia norėdami pradėti pokalbį ar prisijungti prie kanalo."
|
#~ "Spustelėkite čia norėdami pradėti pokalbį ar prisijungti prie kanalo."
|
||||||
|
|
|
@ -1154,3 +1154,20 @@ msgstr ""
|
||||||
#: main/data/manage_accounts/add_account_dialog.ui:506
|
#: main/data/manage_accounts/add_account_dialog.ui:506
|
||||||
msgid "Finish"
|
msgid "Finish"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :5
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :103
|
||||||
|
msgid "Change password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :21
|
||||||
|
msgid "Current password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :43
|
||||||
|
msgid "New password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :65
|
||||||
|
msgid "Confirm new password"
|
||||||
|
msgstr ""
|
||||||
|
|
|
@ -1167,6 +1167,23 @@ msgstr "Ferdig oppsatt."
|
||||||
msgid "Finish"
|
msgid "Finish"
|
||||||
msgstr "Fullfør"
|
msgstr "Fullfør"
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :5
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :103
|
||||||
|
msgid "Change password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :21
|
||||||
|
msgid "Current password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :43
|
||||||
|
msgid "New password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :65
|
||||||
|
msgid "Confirm new password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#~ msgid "Click here to start a conversation or join a channel."
|
#~ msgid "Click here to start a conversation or join a channel."
|
||||||
#~ msgstr "Klikk her for å starte en samtale, eller ta del i en kanal."
|
#~ msgstr "Klikk her for å starte en samtale, eller ta del i en kanal."
|
||||||
|
|
||||||
|
|
|
@ -1163,6 +1163,23 @@ msgstr "Klaar!"
|
||||||
msgid "Finish"
|
msgid "Finish"
|
||||||
msgstr "Voltooien"
|
msgstr "Voltooien"
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :5
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :103
|
||||||
|
msgid "Change password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :21
|
||||||
|
msgid "Current password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :43
|
||||||
|
msgid "New password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :65
|
||||||
|
msgid "Confirm new password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#~ msgid "Click here to start a conversation or join a channel."
|
#~ msgid "Click here to start a conversation or join a channel."
|
||||||
#~ msgstr ""
|
#~ msgstr ""
|
||||||
#~ "Klik hier om een gesprek te starten of deel te nemen aan een kanaal."
|
#~ "Klik hier om een gesprek te starten of deel te nemen aan een kanaal."
|
||||||
|
|
|
@ -1165,6 +1165,23 @@ msgstr "Tot es prèst !"
|
||||||
msgid "Finish"
|
msgid "Finish"
|
||||||
msgstr "Terminar"
|
msgstr "Terminar"
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :5
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :103
|
||||||
|
msgid "Change password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :21
|
||||||
|
msgid "Current password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :43
|
||||||
|
msgid "New password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :65
|
||||||
|
msgid "Confirm new password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#~ msgid "Click here to start a conversation or join a channel."
|
#~ msgid "Click here to start a conversation or join a channel."
|
||||||
#~ msgstr "Clicatz aquí per començar una conversacion o jónher una sala."
|
#~ msgstr "Clicatz aquí per començar una conversacion o jónher una sala."
|
||||||
|
|
||||||
|
|
|
@ -1169,6 +1169,23 @@ msgstr "Wszystko gotowe!"
|
||||||
msgid "Finish"
|
msgid "Finish"
|
||||||
msgstr "Zakończ"
|
msgstr "Zakończ"
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :5
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :103
|
||||||
|
msgid "Change password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :21
|
||||||
|
msgid "Current password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :43
|
||||||
|
msgid "New password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :65
|
||||||
|
msgid "Confirm new password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#~ msgid "Click here to start a conversation or join a channel."
|
#~ msgid "Click here to start a conversation or join a channel."
|
||||||
#~ msgstr "Kliknij tutaj, aby rozpocząć rozmowę albo dołączyć do kanału."
|
#~ msgstr "Kliknij tutaj, aby rozpocząć rozmowę albo dołączyć do kanału."
|
||||||
|
|
||||||
|
|
|
@ -1163,5 +1163,22 @@ msgstr "Tudo configurado!"
|
||||||
msgid "Finish"
|
msgid "Finish"
|
||||||
msgstr "Finalizado"
|
msgstr "Finalizado"
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :5
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :103
|
||||||
|
msgid "Change password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :21
|
||||||
|
msgid "Current password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :43
|
||||||
|
msgid "New password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :65
|
||||||
|
msgid "Confirm new password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#~ msgid "Click here to start a conversation or join a channel."
|
#~ msgid "Click here to start a conversation or join a channel."
|
||||||
#~ msgstr "Clique aqui para iniciar uma conversa or entrar num canal."
|
#~ msgstr "Clique aqui para iniciar uma conversa or entrar num canal."
|
||||||
|
|
|
@ -1164,6 +1164,23 @@ msgstr "Tudo configurado!"
|
||||||
msgid "Finish"
|
msgid "Finish"
|
||||||
msgstr "Finalizado"
|
msgstr "Finalizado"
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :5
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :103
|
||||||
|
msgid "Change password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :21
|
||||||
|
msgid "Current password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :43
|
||||||
|
msgid "New password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :65
|
||||||
|
msgid "Confirm new password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#~ msgid "Click here to start a conversation or join a channel."
|
#~ msgid "Click here to start a conversation or join a channel."
|
||||||
#~ msgstr "Clique aqui para inicial uma conversa ou entrar em um canal."
|
#~ msgstr "Clique aqui para inicial uma conversa ou entrar em um canal."
|
||||||
|
|
||||||
|
|
|
@ -1170,6 +1170,23 @@ msgstr "Gata!"
|
||||||
msgid "Finish"
|
msgid "Finish"
|
||||||
msgstr "Finalizare"
|
msgstr "Finalizare"
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :5
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :103
|
||||||
|
msgid "Change password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :21
|
||||||
|
msgid "Current password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :43
|
||||||
|
msgid "New password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :65
|
||||||
|
msgid "Confirm new password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#~ msgid "Click here to start a conversation or join a channel."
|
#~ msgid "Click here to start a conversation or join a channel."
|
||||||
#~ msgstr ""
|
#~ msgstr ""
|
||||||
#~ "Apăsați aici pentru a porni o conversație sau a vă alătura unui canal."
|
#~ "Apăsați aici pentru a porni o conversație sau a vă alătura unui canal."
|
||||||
|
|
102
main/po/ru.po
102
main/po/ru.po
|
@ -47,6 +47,7 @@ msgstr "доставка не удалась"
|
||||||
#: main/src/ui/chat_input/encryption_button.vala:26
|
#: main/src/ui/chat_input/encryption_button.vala:26
|
||||||
#: main/src/ui/conversation_content_view/conversation_item_skeleton.vala:163
|
#: main/src/ui/conversation_content_view/conversation_item_skeleton.vala:163
|
||||||
#: main/data/menu_encryption.ui:14
|
#: main/data/menu_encryption.ui:14
|
||||||
|
#: main/data/default_encryption_dialog.ui:57
|
||||||
msgid "Unencrypted"
|
msgid "Unencrypted"
|
||||||
msgstr "Не зашифровано"
|
msgstr "Не зашифровано"
|
||||||
|
|
||||||
|
@ -562,7 +563,7 @@ msgstr "Уведомления"
|
||||||
|
|
||||||
#: main/src/ui/contact_details/settings_provider.vala:55
|
#: main/src/ui/contact_details/settings_provider.vala:55
|
||||||
msgid "Pin conversation"
|
msgid "Pin conversation"
|
||||||
msgstr ""
|
msgstr "Закрепить беседу"
|
||||||
|
|
||||||
#: main/src/ui/contact_details/settings_provider.vala:55
|
#: main/src/ui/contact_details/settings_provider.vala:55
|
||||||
msgid "Pins the conversation to the top of the conversation list"
|
msgid "Pins the conversation to the top of the conversation list"
|
||||||
|
@ -825,16 +826,16 @@ msgstr "Прочтите %s, чтобы узнать о процессе авт
|
||||||
|
|
||||||
#: main/src/ui/conversation_content_view/message_widget.vala:213
|
#: main/src/ui/conversation_content_view/message_widget.vala:213
|
||||||
msgid "Edit message"
|
msgid "Edit message"
|
||||||
msgstr ""
|
msgstr "Редактировать сообщение"
|
||||||
|
|
||||||
#: main/src/ui/conversation_content_view/reactions_widget.vala:102
|
#: main/src/ui/conversation_content_view/reactions_widget.vala:102
|
||||||
msgid "You"
|
msgid "You"
|
||||||
msgstr ""
|
msgstr "Вы"
|
||||||
|
|
||||||
#: main/src/ui/conversation_content_view/reactions_widget.vala:128
|
#: main/src/ui/conversation_content_view/reactions_widget.vala:128
|
||||||
#: main/src/ui/conversation_content_view/item_actions.vala:8
|
#: main/src/ui/conversation_content_view/item_actions.vala:8
|
||||||
msgid "Add reaction"
|
msgid "Add reaction"
|
||||||
msgstr ""
|
msgstr "Добавить реакцию"
|
||||||
|
|
||||||
#: main/src/ui/conversation_content_view/file_image_widget.vala:53
|
#: main/src/ui/conversation_content_view/file_image_widget.vala:53
|
||||||
#: main/src/ui/conversation_content_view/file_default_widget.vala:57
|
#: main/src/ui/conversation_content_view/file_default_widget.vala:57
|
||||||
|
@ -946,7 +947,7 @@ msgstr "несколько секунд"
|
||||||
|
|
||||||
#: main/src/ui/conversation_content_view/conversation_item_skeleton.vala:191
|
#: main/src/ui/conversation_content_view/conversation_item_skeleton.vala:191
|
||||||
msgid "Delivered"
|
msgid "Delivered"
|
||||||
msgstr ""
|
msgstr "Доставленo"
|
||||||
|
|
||||||
#: main/src/ui/conversation_content_view/conversation_item_skeleton.vala:195
|
#: main/src/ui/conversation_content_view/conversation_item_skeleton.vala:195
|
||||||
msgid "Read"
|
msgid "Read"
|
||||||
|
@ -958,15 +959,15 @@ msgstr "Этот контакт хочет добавить вас в свой
|
||||||
|
|
||||||
#: main/src/ui/conversation_content_view/item_actions.vala:21
|
#: main/src/ui/conversation_content_view/item_actions.vala:21
|
||||||
msgid "This conversation does not support reactions."
|
msgid "This conversation does not support reactions."
|
||||||
msgstr ""
|
msgstr "Этот разговор не поддерживает реакции."
|
||||||
|
|
||||||
#: main/src/ui/conversation_content_view/item_actions.vala:33
|
#: main/src/ui/conversation_content_view/item_actions.vala:33
|
||||||
msgid "Reply"
|
msgid "Reply"
|
||||||
msgstr ""
|
msgstr "Ответить"
|
||||||
|
|
||||||
#: main/src/ui/conversation_content_view/item_actions.vala:43
|
#: main/src/ui/conversation_content_view/item_actions.vala:43
|
||||||
msgid "This conversation does not support replies."
|
msgid "This conversation does not support replies."
|
||||||
msgstr ""
|
msgstr "Этот разговор не поддерживает ответы"
|
||||||
|
|
||||||
#: main/src/ui/conversation_content_view/file_default_widget.vala:64
|
#: main/src/ui/conversation_content_view/file_default_widget.vala:64
|
||||||
#, c-format
|
#, c-format
|
||||||
|
@ -1005,7 +1006,7 @@ msgstr "Тут пустовато"
|
||||||
|
|
||||||
#: main/data/unified_main_content.ui:47
|
#: main/data/unified_main_content.ui:47
|
||||||
msgid "Click + to start a chat or join a channel"
|
msgid "Click + to start a chat or join a channel"
|
||||||
msgstr ""
|
msgstr "Нажмите +, чтобы начать чат или присоединиться к каналу"
|
||||||
|
|
||||||
#: main/data/add_conversation/conference_details_fragment.ui:20
|
#: main/data/add_conversation/conference_details_fragment.ui:20
|
||||||
#: main/data/add_conversation/add_groupchat_dialog.ui:40
|
#: main/data/add_conversation/add_groupchat_dialog.ui:40
|
||||||
|
@ -1027,17 +1028,49 @@ msgstr "Псевдоним"
|
||||||
msgid "Add Contact"
|
msgid "Add Contact"
|
||||||
msgstr "Добавить контакт"
|
msgstr "Добавить контакт"
|
||||||
|
|
||||||
#: main/data/settings_dialog.ui:41
|
#: main/data/settings_dialog.ui:14
|
||||||
|
msgid "Default encryption for 1-on-1 chats"
|
||||||
|
msgstr "Шифрование по умолчанию для 1-на-1 чатов"
|
||||||
|
|
||||||
|
#: main/data/settings_dialog.ui:19
|
||||||
|
msgid "Ask"
|
||||||
|
msgstr "Спрашивать"
|
||||||
|
|
||||||
|
#: main/data/settings_dialog.ui:57
|
||||||
|
msgid "Send _Typing Notifications"
|
||||||
|
msgstr "Отправлять уведомления при наборе сообщения"
|
||||||
|
|
||||||
|
#: main/data/settings_dialog.ui:85
|
||||||
|
msgid "_Notifications"
|
||||||
|
msgstr "Уведомления"
|
||||||
|
|
||||||
|
#: main/data/settings_dialog.ui:69
|
||||||
|
msgid "Send _Read Receipts"
|
||||||
|
msgstr "Отправлять уведомления о прочтении"
|
||||||
|
|
||||||
|
#: main/data/settings_dialog.ui:86
|
||||||
msgid "Notify when a new message arrives"
|
msgid "Notify when a new message arrives"
|
||||||
msgstr "Уведомлять о новых сообщениях"
|
msgstr "Уведомлять о новых сообщениях"
|
||||||
|
|
||||||
#: main/data/settings_dialog.ui:50
|
#: main/data/settings_dialog.ui:102
|
||||||
msgid "Convert smileys to emojis"
|
msgid "_Convert Smileys to Emoji"
|
||||||
msgstr "Превращать смайлы в эмодзи"
|
msgstr "Превращать смайлы в эмодзи"
|
||||||
|
|
||||||
#: main/data/settings_dialog.ui:59
|
#: main/data/settings_dialog.ui:118
|
||||||
msgid "Check spelling"
|
msgid "_Display send button"
|
||||||
msgstr "Проверка орфографии"
|
msgstr "Показывать кнопку отправки"
|
||||||
|
|
||||||
|
#: main/data/settings_dialog.ui:130
|
||||||
|
msgid "_Use Enter key to start a new line"
|
||||||
|
msgstr "Использовать Enter для вставки новой строки"
|
||||||
|
|
||||||
|
#: main/data/settings_dialog.ui:131
|
||||||
|
msgid "If disabled, use Shift+Enter to start a new line"
|
||||||
|
msgstr "Если опция недоступна, используйте Shift+Enter для вставки новой строки"
|
||||||
|
|
||||||
|
#: main/data/settings_dialog.ui:147
|
||||||
|
msgid "_Dark theme"
|
||||||
|
msgstr "Тёмная тема"
|
||||||
|
|
||||||
#: main/data/im.dino.Dino.appdata.xml.in:7
|
#: main/data/im.dino.Dino.appdata.xml.in:7
|
||||||
msgid "Modern XMPP Chat Client"
|
msgid "Modern XMPP Chat Client"
|
||||||
|
@ -1167,6 +1200,45 @@ msgstr "Всё готово!"
|
||||||
msgid "Finish"
|
msgid "Finish"
|
||||||
msgstr "Закончить"
|
msgstr "Закончить"
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :5
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :103
|
||||||
|
msgid "Change password"
|
||||||
|
msgstr "Изменить пароль"
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :21
|
||||||
|
msgid "Current password"
|
||||||
|
msgstr "Текущий пароль"
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :43
|
||||||
|
msgid "New password"
|
||||||
|
msgstr "Новый пароль"
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :65
|
||||||
|
msgid "Confirm new password"
|
||||||
|
msgstr "Подтверждение пароля"
|
||||||
|
|
||||||
|
#: main/data/default_encryption_dialog.ui :27
|
||||||
|
msgid ""
|
||||||
|
"You are opening a new conversation without having set end-to-end encryption by default.\n\n"
|
||||||
|
"It is strongly recommended to enable it to prevent your messages from being read by third parties.\n\n"
|
||||||
|
"Please select an option to start this conversation with. Choosing one of the encryption methods will also set it as default in the global settings.\n"
|
||||||
|
msgstr ""
|
||||||
|
"Вы начинаете новый диалог без установления настроек сквозного шифрования по умолчанию.\n\n"
|
||||||
|
"Крайне рекомендуется включить его, чтобы исключить перехват ваших сообщений злоумышленниками.\n\n"
|
||||||
|
"Пожалуйста, выберите с какими настройками шифрования начать этот диалог. Выбирая одну из них, вы установите эту же настройку глобально по умолчанию для других диалогов.\n"
|
||||||
|
|
||||||
|
#: main/data/default_encryption_dialog.ui :38
|
||||||
|
msgid "OMEMO (automatic setup)"
|
||||||
|
msgstr "OMEMO (настроится автоматически)"
|
||||||
|
|
||||||
|
#: main/data/default_encryption_dialog.ui :47
|
||||||
|
msgid "OpenPGP (external setup required)"
|
||||||
|
msgstr "OpenPGP (потребует ручной настройки)"
|
||||||
|
|
||||||
|
#: main/data/default_encryption_dialog.ui :67
|
||||||
|
msgid "Apply"
|
||||||
|
msgstr "Применить"
|
||||||
|
|
||||||
#~ msgid "Click here to start a conversation or join a channel."
|
#~ msgid "Click here to start a conversation or join a channel."
|
||||||
#~ msgstr "Нажмите здесь, чтобы начать беседу или присоединиться к каналу."
|
#~ msgstr "Нажмите здесь, чтобы начать беседу или присоединиться к каналу."
|
||||||
|
|
||||||
|
|
|
@ -1163,5 +1163,22 @@ msgstr "Gjithçka e ujdisur!"
|
||||||
msgid "Finish"
|
msgid "Finish"
|
||||||
msgstr "Përfundoje"
|
msgstr "Përfundoje"
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :5
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :103
|
||||||
|
msgid "Change password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :21
|
||||||
|
msgid "Current password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :43
|
||||||
|
msgid "New password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :65
|
||||||
|
msgid "Confirm new password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#~ msgid "Click here to start a conversation or join a channel."
|
#~ msgid "Click here to start a conversation or join a channel."
|
||||||
#~ msgstr "Klikoni këtu që të nisni një bisedë ose të hyni në një kanal."
|
#~ msgstr "Klikoni këtu që të nisni një bisedë ose të hyni në një kanal."
|
||||||
|
|
|
@ -1163,6 +1163,23 @@ msgstr "Färdigt!"
|
||||||
msgid "Finish"
|
msgid "Finish"
|
||||||
msgstr "Slutför"
|
msgstr "Slutför"
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :5
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :103
|
||||||
|
msgid "Change password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :21
|
||||||
|
msgid "Current password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :43
|
||||||
|
msgid "New password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :65
|
||||||
|
msgid "Confirm new password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#~ msgid "Click here to start a conversation or join a channel."
|
#~ msgid "Click here to start a conversation or join a channel."
|
||||||
#~ msgstr "Klicka här för att starta en konversation eller gå med i en kanal."
|
#~ msgstr "Klicka här för att starta en konversation eller gå med i en kanal."
|
||||||
|
|
||||||
|
|
|
@ -1153,3 +1153,20 @@ msgstr ""
|
||||||
#: main/data/manage_accounts/add_account_dialog.ui:506
|
#: main/data/manage_accounts/add_account_dialog.ui:506
|
||||||
msgid "Finish"
|
msgid "Finish"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :5
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :103
|
||||||
|
msgid "Change password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :21
|
||||||
|
msgid "Current password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :43
|
||||||
|
msgid "New password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :65
|
||||||
|
msgid "Confirm new password"
|
||||||
|
msgstr ""
|
||||||
|
|
|
@ -1162,6 +1162,23 @@ msgstr "Hepsi tamam!"
|
||||||
msgid "Finish"
|
msgid "Finish"
|
||||||
msgstr "Bitir"
|
msgstr "Bitir"
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :5
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :103
|
||||||
|
msgid "Change password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :21
|
||||||
|
msgid "Current password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :43
|
||||||
|
msgid "New password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :65
|
||||||
|
msgid "Confirm new password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#~ msgid "Click here to start a conversation or join a channel."
|
#~ msgid "Click here to start a conversation or join a channel."
|
||||||
#~ msgstr "Bir sohbet başlatmak ya da kanala katılmak için buraya tıkla."
|
#~ msgstr "Bir sohbet başlatmak ya da kanala katılmak için buraya tıkla."
|
||||||
|
|
||||||
|
|
|
@ -1158,3 +1158,20 @@ msgstr ""
|
||||||
#: main/data/manage_accounts/add_account_dialog.ui:506
|
#: main/data/manage_accounts/add_account_dialog.ui:506
|
||||||
msgid "Finish"
|
msgid "Finish"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :5
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :103
|
||||||
|
msgid "Change password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :21
|
||||||
|
msgid "Current password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :43
|
||||||
|
msgid "New password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :65
|
||||||
|
msgid "Confirm new password"
|
||||||
|
msgstr ""
|
||||||
|
|
|
@ -1155,6 +1155,23 @@ msgstr "都准备好了!"
|
||||||
msgid "Finish"
|
msgid "Finish"
|
||||||
msgstr "完成"
|
msgstr "完成"
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :5
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :103
|
||||||
|
msgid "Change password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :21
|
||||||
|
msgid "Current password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :43
|
||||||
|
msgid "New password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: main/src/ui/manage_accounts/change_password_dialog.vala :65
|
||||||
|
msgid "Confirm new password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#~ msgid "Click here to start a conversation or join a channel."
|
#~ msgid "Click here to start a conversation or join a channel."
|
||||||
#~ msgstr "点击此处以开始对话或加入频道。"
|
#~ msgstr "点击此处以开始对话或加入频道。"
|
||||||
|
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue