1
0
Fork 0
forked from lthn/blockchain

Merge branch 'release'

This commit is contained in:
cryptozoidberg 2020-11-12 23:37:09 +03:00
commit 04ba1f64f4
No known key found for this signature in database
GPG key ID: 22DEB97A54C6FDEC
142 changed files with 20474 additions and 1154 deletions

View file

@ -189,6 +189,13 @@ if(CMAKE_SYSTEM_NAME STREQUAL "iOS")
set(Boost_LIBRARY_DIRS "/Users/roky/projects/Zano/mobile_repo/ofxiOSBoost/libs/boost/ios/")
set(Boost_LIBRARIES "libboost.a")
set(Boost_VERSION "ofxiOSBoost 1.60.0")
#workaround for new XCode 12 policy for builds(now it includes a slice for the "arm64" when builds for simulator)
set(__iphoneos_archs "armv7 armv7s arm64")
set(__iphonesimulator_archs "i386 x86_64")
set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=iphoneos*] "${__iphoneos_archs}")
set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=iphoneos*] "${__iphoneos_archs}")
set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=iphonesimulator*] "${__iphonesimulator_archs}")
set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=iphonesimulator*] "${__iphonesimulator_archs}")
elseif(CMAKE_SYSTEM_NAME STREQUAL "Android")
set(Boost_INCLUDE_DIRS "/Users/roky/projects/Zano/mobile_repo/Boost-for-Android-Prebuilt/1.69.0/include")
set(Boost_LIBRARY_DIRS "/Users/roky/projects/Zano/mobile_repo/Boost-for-Android-Prebuilt/1.69.0/libs/llvm/${CMAKE_ANDROID_ARCH_ABI}/")

View file

@ -132,8 +132,10 @@ extern int cacheflush(char *addr, int nbytes, int cache);
#ifdef _WIN32
typedef int64_t off64_t;
#elif __APPLE__
typedef off_t off64_t;
#else
//typedef off_t off64_t;
#endif

View file

@ -14,6 +14,7 @@ MACRO(INIT_SHARED_PCH)
IF(MSVC)
set_property(SOURCE "pch/stdafx.cpp" APPEND_STRING PROPERTY COMPILE_FLAGS " /Fo$(OutDir) /Z7 /Fd$(OutDir)vc$(PlatformToolsetVersion).pdb /Ycstdafx.h /Fp$(TargetDir)pch.pch")
ELSEIF(APPLE OR CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
cmake_minimum_required(VERSION 3.16)
target_precompile_headers(pch PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/pch/stdafx.h")
ENDIF()
ENDIF(USE_PCH)
@ -75,6 +76,7 @@ if(BUILD_GUI)
else()
file(GLOB_RECURSE QTDAEMON gui/qt-daemon/*.cpp gui/qt-daemon/*.h)
endif()
list(FILTER QTDAEMON EXCLUDE REGEX "node_modules")
endif()

View file

@ -37,5 +37,5 @@
#define API_RETURN_CODE_GENESIS_MISMATCH "GENESIS_MISMATCH"
#define API_RETURN_CODE_DISCONNECTED "DISCONNECTED"
#define API_RETURN_CODE_UNINITIALIZED "UNINITIALIZED"
#define API_RETURN_CODE_TX_IS_TOO_BIG "TX_IS_TOO_BIG"
#define API_RETURN_CODE_TX_REJECTED "TX_REJECTED"

View file

@ -65,6 +65,8 @@ namespace currency
bool store(const std::string& file_path);
void make_account_watch_only();
bool is_watch_only() const { return m_keys.spend_secret_key == currency::null_skey; }
bool is_auditable() const { return m_keys.account_address.is_auditable(); }
template <class t_archive>
inline void serialize(t_archive &a, const unsigned int /*ver*/)

View file

@ -239,6 +239,28 @@ QString MainWindow::get_tx_pool_info()
CATCH_ENTRY_FAIL_API_RESPONCE();
}
QString MainWindow::request_dummy()
{
static int code_ = 0;
TRY_ENTRY();
LOG_API_TIMING();
PREPARE_RESPONSE(currency::COMMAND_RPC_GET_POOL_INFO::response, ar);
if (code_ == 2)
{
code_ = -1;
ar.error_code = API_RETURN_CODE_CORE_BUSY;
}
else
{
ar.error_code = API_RETURN_CODE_OK;
}
++code_;
return MAKE_RESPONSE(ar);
CATCH_ENTRY_FAIL_API_RESPONCE();
}
QString MainWindow::get_default_fee()
{
TRY_ENTRY();
@ -734,15 +756,8 @@ QString MainWindow::is_remnotenode_mode_preconfigured()
QString MainWindow::start_backend(const QString& params)
{
TRY_ENTRY();
view::start_backend_params sbp = AUTO_VAL_INIT(sbp);
view::api_response ar = AUTO_VAL_INIT(ar);
if (!epee::serialization::load_t_from_json(sbp, params.toStdString()))
{
ar.error_code = API_RETURN_CODE_BAD_ARG;
return MAKE_RESPONSE(ar);
}
bool r = m_backend.start();
if (!r)
{
@ -758,13 +773,18 @@ bool MainWindow::update_wallet_status(const view::wallet_status_info& wsi)
{
TRY_ENTRY();
m_wallet_states->operator [](wsi.wallet_id) = wsi.wallet_state;
std::string json_str_pub;
epee::serialization::store_t_to_json(static_cast<const view::wallet_status_info_base&>(wsi), json_str_pub, 0, epee::serialization::eol_lf);
LOG_PRINT_L0(get_wallet_log_prefix(wsi.wallet_id) + "SENDING SIGNAL -> [update_wallet_status]:" << std::endl << json_str_pub);
std::string json_str;
epee::serialization::store_t_to_json(wsi, json_str, 0, epee::serialization::eol_lf);
LOG_PRINT_L0(get_wallet_log_prefix(wsi.wallet_id) + "SENDING SIGNAL -> [update_wallet_status]:" << std::endl << json_str );
QMetaObject::invokeMethod(this, "update_wallet_status", Qt::QueuedConnection, Q_ARG(QString, json_str.c_str()));
return true;
CATCH_ENTRY2(false);
}
bool MainWindow::set_options(const view::gui_options& opt)
{
TRY_ENTRY();
@ -920,6 +940,15 @@ QString MainWindow::get_os_version()
CATCH_ENTRY2(API_RETURN_CODE_INTERNAL_ERROR);
}
QString MainWindow::get_network_type()
{
#if defined(TESTNET)
return "testnet";
#else
return "mainnet";
#endif
}
QString MainWindow::get_alias_coast(const QString& param)
{
TRY_ENTRY();
@ -946,9 +975,12 @@ QString MainWindow::set_localization_strings(const QString param)
else
{
m_localization = lr.strings;
m_quit_action->setText(QString().fromUtf8(m_localization[localization_id_quit].c_str()));
m_restore_action->setText(QString().fromUtf8(m_localization[localization_id_tray_menu_show].c_str()));
m_minimize_action->setText(QString().fromUtf8(m_localization[localization_id_tray_menu_minimize].c_str()));
if(m_quit_action)
m_quit_action->setText(QString::fromStdString(m_localization[localization_id_quit]));
if(m_restore_action)
m_restore_action->setText(QString::fromStdString(m_localization[localization_id_tray_menu_show]));
if(m_minimize_action)
m_minimize_action->setText(QString::fromStdString(m_localization[localization_id_tray_menu_minimize]));
resp.error_code = API_RETURN_CODE_OK;
LOG_PRINT_L0("New localization set, language title: " << lr.language_title << ", strings " << lr.strings.size());
}

View file

@ -91,6 +91,7 @@ public:
QString get_version();
QString get_os_version();
QString get_network_type();
QString transfer(const QString& json_transfer_object);
QString have_secure_app_data();
QString drop_secure_app_data();
@ -158,6 +159,9 @@ public:
QString is_remnotenode_mode_preconfigured();
QString start_backend(const QString& params);
//for test purposes onlys
QString request_dummy();
signals:
void quit_requested(const QString str);
void update_daemon_state(const QString str);

View file

@ -147,6 +147,12 @@
"TIME3": "1 hour",
"TIME4": "Never"
},
"SCALE": {
"75": "75% scale",
"100": "100% scale",
"125": "125% scale",
"150": "150% scale"
},
"MASTER_PASSWORD": {
"TITLE": "Update master password",
"OLD": "Old password",
@ -194,7 +200,7 @@
"ASSIGN_ALIAS": {
"NAME": {
"LABEL": "Alias",
"PLACEHOLDER": "@ Enter alias",
"PLACEHOLDER": " Enter alias",
"TOOLTIP": "An alias is a shortened form or your account. An alias can only include Latin letters, numbers and characters “.” and “-”. It must start with “@”."
},
"COMMENT": {
@ -206,7 +212,7 @@
"BUTTON_ASSIGN": "Assign",
"FORM_ERRORS": {
"NAME_REQUIRED": "Name is required",
"NAME_WRONG": "Alias has wrong name",
"NAME_WRONG": "Invalid name: allowed symbols \"0-9\", \"a-z\", \"-\", \".\"",
"NAME_LENGTH": "The alias must be 6-25 characters long",
"NAME_EXISTS": "Alias name already exists",
"NO_MONEY": "You do not have enough funds to assign this alias",

View file

@ -147,6 +147,12 @@
"TIME3": "1 hour",
"TIME4": "Never"
},
"SCALE": {
"75": "75% scale",
"100": "100% scale",
"125": "125% scale",
"150": "150% scale"
},
"MASTER_PASSWORD": {
"TITLE": "Update master password",
"OLD": "Old password",
@ -194,7 +200,7 @@
"ASSIGN_ALIAS": {
"NAME": {
"LABEL": "Alias",
"PLACEHOLDER": "@ Enter alias",
"PLACEHOLDER": " Enter alias",
"TOOLTIP": "An alias is a shortened form or your account. An alias can only include Latin letters, numbers and characters “.” and “-”. It must start with “@”."
},
"COMMENT": {
@ -206,7 +212,7 @@
"BUTTON_ASSIGN": "Assign",
"FORM_ERRORS": {
"NAME_REQUIRED": "Name is required",
"NAME_WRONG": "Alias has wrong name",
"NAME_WRONG": "Invalid name: allowed symbols \"0-9\", \"a-z\", \"-\", \".\"",
"NAME_LENGTH": "The alias must be 6-25 characters long",
"NAME_EXISTS": "Alias name already exists",
"NO_MONEY": "You do not have enough funds to assign this alias",

View file

@ -147,6 +147,12 @@
"TIME3": "1 hour",
"TIME4": "Never"
},
"SCALE": {
"75": "75% scale",
"100": "100% scale",
"125": "125% scale",
"150": "150% scale"
},
"MASTER_PASSWORD": {
"TITLE": "Update master password",
"OLD": "Old password",
@ -194,7 +200,7 @@
"ASSIGN_ALIAS": {
"NAME": {
"LABEL": "Alias",
"PLACEHOLDER": "@ Enter alias",
"PLACEHOLDER": " Enter alias",
"TOOLTIP": "An alias is a shortened form or your account. An alias can only include Latin letters, numbers and characters “.” and “-”. It must start with “@”."
},
"COMMENT": {
@ -206,7 +212,7 @@
"BUTTON_ASSIGN": "Assign",
"FORM_ERRORS": {
"NAME_REQUIRED": "Name is required",
"NAME_WRONG": "Alias has wrong name",
"NAME_WRONG": "Invalid name: allowed symbols \"0-9\", \"a-z\", \"-\", \".\"",
"NAME_LENGTH": "The alias must be 6-25 characters long",
"NAME_EXISTS": "Alias name already exists",
"NO_MONEY": "You do not have enough funds to assign this alias",

View file

@ -147,6 +147,12 @@
"TIME3": "1 hour",
"TIME4": "Never"
},
"SCALE": {
"75": "75% scale",
"100": "100% scale",
"125": "125% scale",
"150": "150% scale"
},
"MASTER_PASSWORD": {
"TITLE": "Update master password",
"OLD": "Old password",
@ -194,7 +200,7 @@
"ASSIGN_ALIAS": {
"NAME": {
"LABEL": "Alias",
"PLACEHOLDER": "@ Enter alias",
"PLACEHOLDER": " Enter alias",
"TOOLTIP": "An alias is a shortened form or your account. An alias can only include Latin letters, numbers and characters “.” and “-”. It must start with “@”."
},
"COMMENT": {
@ -206,7 +212,7 @@
"BUTTON_ASSIGN": "Assign",
"FORM_ERRORS": {
"NAME_REQUIRED": "Name is required",
"NAME_WRONG": "Alias has wrong name",
"NAME_WRONG": "Invalid name: allowed symbols \"0-9\", \"a-z\", \"-\", \".\"",
"NAME_LENGTH": "The alias must be 6-25 characters long",
"NAME_EXISTS": "Alias name already exists",
"NO_MONEY": "You do not have enough funds to assign this alias",

View file

@ -147,6 +147,12 @@
"TIME3": "1 hour",
"TIME4": "Never"
},
"SCALE": {
"75": "75% scale",
"100": "100% scale",
"125": "125% scale",
"150": "150% scale"
},
"MASTER_PASSWORD": {
"TITLE": "Update master password",
"OLD": "Old password",
@ -194,7 +200,7 @@
"ASSIGN_ALIAS": {
"NAME": {
"LABEL": "Alias",
"PLACEHOLDER": "@ Enter alias",
"PLACEHOLDER": " Enter alias",
"TOOLTIP": "An alias is a shortened form or your account. An alias can only include Latin letters, numbers and characters “.” and “-”. It must start with “@”."
},
"COMMENT": {
@ -206,7 +212,7 @@
"BUTTON_ASSIGN": "Assign",
"FORM_ERRORS": {
"NAME_REQUIRED": "Name is required",
"NAME_WRONG": "Alias has wrong name",
"NAME_WRONG": "Invalid name: allowed symbols \"0-9\", \"a-z\", \"-\", \".\"",
"NAME_LENGTH": "The alias must be 6-25 characters long",
"NAME_EXISTS": "Alias name already exists",
"NO_MONEY": "You do not have enough funds to assign this alias",

View file

@ -147,6 +147,12 @@
"TIME3": "1 Stunde",
"TIME4": "Nie"
},
"SCALE": {
"75": "75% Rahmen",
"100": "100% Rahmen",
"125": "125% Rahmen",
"150": "150% Rahmen"
},
"MASTER_PASSWORD": {
"TITLE": "Master-Passwort aktualisieren",
"OLD": "Altes Passwort",
@ -194,7 +200,7 @@
"ASSIGN_ALIAS": {
"NAME": {
"LABEL": "Alias",
"PLACEHOLDER": "@ Alias eingeben",
"PLACEHOLDER": " Alias eingeben",
"TOOLTIP": "Ein Alias ist eine verkürzte Form Ihres Kontos. Ein Alias kann nur lateinische Buchstaben, Zahlen und die Zeichen „.“ und “-” enthalten. Es muss mit “@” beginnen."
},
"COMMENT": {
@ -206,7 +212,7 @@
"BUTTON_ASSIGN": "Zuweisen",
"FORM_ERRORS": {
"NAME_REQUIRED": "Name ist erforderlich",
"NAME_WRONG": "Alias hat einen falschen Namen",
"NAME_WRONG": "Ungültiger Name: zulässige Symbole \"0-9\", \"a-z\", \"-\", \".\"",
"NAME_LENGTH": "Der Alias muss 6-25 Zeichen lang sein",
"NAME_EXISTS": "Alias-Name existiert bereits",
"NO_MONEY": "Du hast nicht genug Geldmittel, um diesen Alias zuzuweisen",

View file

@ -147,6 +147,12 @@
"TIME3": "1 hour",
"TIME4": "Never"
},
"SCALE": {
"75": "75% scale",
"100": "100% scale",
"125": "125% scale",
"150": "150% scale"
},
"MASTER_PASSWORD": {
"TITLE": "Update master password",
"OLD": "Old password",
@ -194,7 +200,7 @@
"ASSIGN_ALIAS": {
"NAME": {
"LABEL": "Alias",
"PLACEHOLDER": "@ Enter alias",
"PLACEHOLDER": " Enter alias",
"TOOLTIP": "An alias is a shortened form or your account. An alias can only include Latin letters, numbers and characters “.” and “-”. It must start with “@”."
},
"COMMENT": {

View file

@ -223,7 +223,7 @@
"ASSIGN_ALIAS": {
"NAME": {
"LABEL": "Alias",
"PLACEHOLDER": "@ Enter alias",
"PLACEHOLDER": " Enter alias",
"TOOLTIP": "An alias is a shortened form or your account. An alias can only include Latin letters, numbers and characters “.” and “-”. It must start with “@”."
},
"COMMENT": {
@ -235,7 +235,7 @@
"BUTTON_ASSIGN": "Assign",
"FORM_ERRORS": {
"NAME_REQUIRED": "Name is required",
"NAME_WRONG": "Alias has wrong name",
"NAME_WRONG": "Invalid name: allowed symbols \"0-9\", \"a-z\", \"-\", \".\"",
"NAME_LENGTH": "The alias must be 6-25 characters long",
"NAME_EXISTS": "Alias name already exists",
"NO_MONEY": "You do not have enough funds to assign this alias",

View file

@ -147,6 +147,12 @@
"TIME3": "1 hour",
"TIME4": "Never"
},
"SCALE": {
"75": "75% scale",
"100": "100% scale",
"125": "125% scale",
"150": "150% scale"
},
"MASTER_PASSWORD": {
"TITLE": "Update master password",
"OLD": "Old password",
@ -194,7 +200,7 @@
"ASSIGN_ALIAS": {
"NAME": {
"LABEL": "Alias",
"PLACEHOLDER": "@ Enter alias",
"PLACEHOLDER": " Enter alias",
"TOOLTIP": "An alias is a shortened form or your account. An alias can only include Latin letters, numbers and characters “.” and “-”. It must start with “@”."
},
"COMMENT": {
@ -206,7 +212,7 @@
"BUTTON_ASSIGN": "Assign",
"FORM_ERRORS": {
"NAME_REQUIRED": "Name is required",
"NAME_WRONG": "Alias has wrong name",
"NAME_WRONG": "Nombre no válido: símbolos permitidos \"0-9\", \"a-z\", \"-\", \".\"",
"NAME_LENGTH": "The alias must be 6-25 characters long",
"NAME_EXISTS": "Alias name already exists",
"NO_MONEY": "You do not have enough funds to assign this alias",

View file

@ -147,6 +147,12 @@
"TIME3": "1 hour",
"TIME4": "Never"
},
"SCALE": {
"75": "75% scale",
"100": "100% scale",
"125": "125% scale",
"150": "150% scale"
},
"MASTER_PASSWORD": {
"TITLE": "Update master password",
"OLD": "Old password",
@ -194,7 +200,7 @@
"ASSIGN_ALIAS": {
"NAME": {
"LABEL": "Alias",
"PLACEHOLDER": "@ Enter alias",
"PLACEHOLDER": " Enter alias",
"TOOLTIP": "An alias is a shortened form or your account. An alias can only include Latin letters, numbers and characters “.” and “-”. It must start with “@”."
},
"COMMENT": {
@ -206,7 +212,7 @@
"BUTTON_ASSIGN": "Assign",
"FORM_ERRORS": {
"NAME_REQUIRED": "Name is required",
"NAME_WRONG": "Alias has wrong name",
"NAME_WRONG": "Invalid name: allowed symbols \"0-9\", \"a-z\", \"-\", \".\"",
"NAME_LENGTH": "The alias must be 6-25 characters long",
"NAME_EXISTS": "Alias name already exists",
"NO_MONEY": "You do not have enough funds to assign this alias",

View file

@ -147,6 +147,12 @@
"TIME3": "1 heure",
"TIME4": "Jamais"
},
"SCALE": {
"75": "75% échelle",
"100": "100% échelle",
"125": "125% échelle",
"150": "150% échelle"
},
"MASTER_PASSWORD": {
"TITLE": "Mettre à jour le mot de passe principal",
"OLD": "Ancien mot de passe",
@ -194,7 +200,7 @@
"ASSIGN_ALIAS": {
"NAME": {
"LABEL": "Alias",
"PLACEHOLDER": "@ Entrer l'alias",
"PLACEHOLDER": " Entrer l'alias",
"TOOLTIP": "Un alias est une forme abréviée pour votre compte. Un alias ne peut inclure que des lettres, des chiffres et des caractères latins « » et « - ». Il doit commencer par « @ »."
},
"COMMENT": {
@ -206,7 +212,7 @@
"BUTTON_ASSIGN": "Assigner",
"FORM_ERRORS": {
"NAME_REQUIRED": "Le nom est requis",
"NAME_WRONG": "L'alias a un nom incorrect",
"NAME_WRONG": "Nom invalide: symboles autorisés \"0-9\", \"a-z\", \"-\", \".\"",
"NAME_LENGTH": "L'alias doit contenir 6-25 caractères",
"NAME_EXISTS": "Alias déjà existant",
"NO_MONEY": "Vous n'avez pas assez de fonds pour assigner cet alias",

View file

@ -147,6 +147,12 @@
"TIME3": "1 hour",
"TIME4": "Never"
},
"SCALE": {
"75": "75% scale",
"100": "100% scale",
"125": "125% scale",
"150": "150% scale"
},
"MASTER_PASSWORD": {
"TITLE": "Update master password",
"OLD": "Old password",
@ -194,7 +200,7 @@
"ASSIGN_ALIAS": {
"NAME": {
"LABEL": "Alias",
"PLACEHOLDER": "@ Enter alias",
"PLACEHOLDER": " Enter alias",
"TOOLTIP": "An alias is a shortened form or your account. An alias can only include Latin letters, numbers and characters “.” and “-”. It must start with “@”."
},
"COMMENT": {
@ -206,7 +212,7 @@
"BUTTON_ASSIGN": "Assign",
"FORM_ERRORS": {
"NAME_REQUIRED": "Name is required",
"NAME_WRONG": "Alias has wrong name",
"NAME_WRONG": "Invalid name: allowed symbols \"0-9\", \"a-z\", \"-\", \".\"",
"NAME_LENGTH": "The alias must be 6-25 characters long",
"NAME_EXISTS": "Alias name already exists",
"NO_MONEY": "You do not have enough funds to assign this alias",

View file

@ -147,6 +147,12 @@
"TIME3": "1 hour",
"TIME4": "Never"
},
"SCALE": {
"75": "75% scale",
"100": "100% scale",
"125": "125% scale",
"150": "150% scale"
},
"MASTER_PASSWORD": {
"TITLE": "Update master password",
"OLD": "Old password",
@ -194,7 +200,7 @@
"ASSIGN_ALIAS": {
"NAME": {
"LABEL": "Alias",
"PLACEHOLDER": "@ Enter alias",
"PLACEHOLDER": " Enter alias",
"TOOLTIP": "An alias is a shortened form or your account. An alias can only include Latin letters, numbers and characters “.” and “-”. It must start with “@”."
},
"COMMENT": {
@ -206,7 +212,7 @@
"BUTTON_ASSIGN": "Assign",
"FORM_ERRORS": {
"NAME_REQUIRED": "Name is required",
"NAME_WRONG": "Alias has wrong name",
"NAME_WRONG": "Invalid name: allowed symbols \"0-9\", \"a-z\", \"-\", \".\"",
"NAME_LENGTH": "The alias must be 6-25 characters long",
"NAME_EXISTS": "Alias name already exists",
"NO_MONEY": "You do not have enough funds to assign this alias",

View file

@ -147,6 +147,12 @@
"TIME3": "1 ora",
"TIME4": "Mai"
},
"SCALE": {
"75": "75% scala",
"100": "100% scala",
"125": "125% scala",
"150": "150% scala"
},
"MASTER_PASSWORD": {
"TITLE": "Aggiorna password principale",
"OLD": "Vecchia password",
@ -194,7 +200,7 @@
"ASSIGN_ALIAS": {
"NAME": {
"LABEL": "Alias",
"PLACEHOLDER": "@ Inserisci alias",
"PLACEHOLDER": " Inserisci alias",
"TOOLTIP": "Un alias è un modulo abbreviato o il tuo account. Un alias può solo includere lettere latine, numeri e caratteri “.” e “-”. Deve iniziare con “@”."
},
"COMMENT": {
@ -206,7 +212,7 @@
"BUTTON_ASSIGN": "Assegna",
"FORM_ERRORS": {
"NAME_REQUIRED": "Il nome è richiesto",
"NAME_WRONG": "L'Alias ha un nome errato",
"NAME_WRONG": "Nome Ungültiger: zulässige Symbole \"0-9\", \"a-z\", \"-\", \".\"",
"NAME_LENGTH": "L'alias deve essere lungo 6-25 caratteri",
"NAME_EXISTS": "Il nome dell'alias esiste già",
"NO_MONEY": "Non hai fondi sufficienti per assegnare questo alias",

View file

@ -147,6 +147,7 @@
"TIME3": "1 hour",
"TIME4": "Never"
},
"MASTER_PASSWORD": {
"TITLE": "Update master password",
"OLD": "Old password",
@ -194,7 +195,7 @@
"ASSIGN_ALIAS": {
"NAME": {
"LABEL": "Alias",
"PLACEHOLDER": "@ Enter alias",
"PLACEHOLDER": " Enter alias",
"TOOLTIP": "An alias is a shortened form or your account. An alias can only include Latin letters, numbers and characters “.” and “-”. It must start with “@”."
},
"COMMENT": {
@ -206,7 +207,7 @@
"BUTTON_ASSIGN": "Assign",
"FORM_ERRORS": {
"NAME_REQUIRED": "Name is required",
"NAME_WRONG": "Alias has wrong name",
"NAME_WRONG": "Invalid name: allowed symbols \"0-9\", \"a-z\", \"-\", \".\"",
"NAME_LENGTH": "The alias must be 6-25 characters long",
"NAME_EXISTS": "Alias name already exists",
"NO_MONEY": "You do not have enough funds to assign this alias",

View file

@ -147,6 +147,12 @@
"TIME3": "1 hour",
"TIME4": "Never"
},
"SCALE": {
"75": "75% scale",
"100": "100% scale",
"125": "125% scale",
"150": "150% scale"
},
"MASTER_PASSWORD": {
"TITLE": "Update master password",
"OLD": "Old password",
@ -194,7 +200,7 @@
"ASSIGN_ALIAS": {
"NAME": {
"LABEL": "Alias",
"PLACEHOLDER": "@ Enter alias",
"PLACEHOLDER": " Enter alias",
"TOOLTIP": "An alias is a shortened form or your account. An alias can only include Latin letters, numbers and characters “.” and “-”. It must start with “@”."
},
"COMMENT": {
@ -206,7 +212,7 @@
"BUTTON_ASSIGN": "Assign",
"FORM_ERRORS": {
"NAME_REQUIRED": "Name is required",
"NAME_WRONG": "Alias has wrong name",
"NAME_WRONG": "Invalid name: allowed symbols \"0-9\", \"a-z\", \"-\", \".\"",
"NAME_LENGTH": "The alias must be 6-25 characters long",
"NAME_EXISTS": "Alias name already exists",
"NO_MONEY": "You do not have enough funds to assign this alias",

View file

@ -147,6 +147,12 @@
"TIME3": "1 hour",
"TIME4": "Never"
},
"SCALE": {
"75": "75% scale",
"100": "100% scale",
"125": "125% scale",
"150": "150% scale"
},
"MASTER_PASSWORD": {
"TITLE": "Update master password",
"OLD": "Old password",
@ -194,7 +200,7 @@
"ASSIGN_ALIAS": {
"NAME": {
"LABEL": "Alias",
"PLACEHOLDER": "@ Enter alias",
"PLACEHOLDER": " Enter alias",
"TOOLTIP": "An alias is a shortened form or your account. An alias can only include Latin letters, numbers and characters “.” and “-”. It must start with “@”."
},
"COMMENT": {
@ -206,7 +212,7 @@
"BUTTON_ASSIGN": "Assign",
"FORM_ERRORS": {
"NAME_REQUIRED": "Name is required",
"NAME_WRONG": "Alias has wrong name",
"NAME_WRONG": "Invalid name: allowed symbols \"0-9\", \"a-z\", \"-\", \".\"",
"NAME_LENGTH": "The alias must be 6-25 characters long",
"NAME_EXISTS": "Alias name already exists",
"NO_MONEY": "You do not have enough funds to assign this alias",

View file

@ -147,6 +147,12 @@
"TIME3": "1 hour",
"TIME4": "Never"
},
"SCALE": {
"75": "75% scale",
"100": "100% scale",
"125": "125% scale",
"150": "150% scale"
},
"MASTER_PASSWORD": {
"TITLE": "Update master password",
"OLD": "Old password",
@ -194,7 +200,7 @@
"ASSIGN_ALIAS": {
"NAME": {
"LABEL": "Alias",
"PLACEHOLDER": "@ Enter alias",
"PLACEHOLDER": " Enter alias",
"TOOLTIP": "An alias is a shortened form or your account. An alias can only include Latin letters, numbers and characters “.” and “-”. It must start with “@”."
},
"COMMENT": {
@ -206,7 +212,7 @@
"BUTTON_ASSIGN": "Assign",
"FORM_ERRORS": {
"NAME_REQUIRED": "Name is required",
"NAME_WRONG": "Alias has wrong name",
"NAME_WRONG": "Invalid name: allowed symbols \"0-9\", \"a-z\", \"-\", \".\"",
"NAME_LENGTH": "The alias must be 6-25 characters long",
"NAME_EXISTS": "Alias name already exists",
"NO_MONEY": "You do not have enough funds to assign this alias",

View file

@ -147,6 +147,12 @@
"TIME3": "1 hour",
"TIME4": "Never"
},
"SCALE": {
"75": "75% scale",
"100": "100% scale",
"125": "125% scale",
"150": "150% scale"
},
"MASTER_PASSWORD": {
"TITLE": "Update master password",
"OLD": "Old password",
@ -194,7 +200,7 @@
"ASSIGN_ALIAS": {
"NAME": {
"LABEL": "Alias",
"PLACEHOLDER": "@ Enter alias",
"PLACEHOLDER": " Enter alias",
"TOOLTIP": "An alias is a shortened form or your account. An alias can only include Latin letters, numbers and characters “.” and “-”. It must start with “@”."
},
"COMMENT": {
@ -206,7 +212,7 @@
"BUTTON_ASSIGN": "Assign",
"FORM_ERRORS": {
"NAME_REQUIRED": "Name is required",
"NAME_WRONG": "Alias has wrong name",
"NAME_WRONG": "Invalid name: allowed symbols \"0-9\", \"a-z\", \"-\", \".\"",
"NAME_LENGTH": "The alias must be 6-25 characters long",
"NAME_EXISTS": "Alias name already exists",
"NO_MONEY": "You do not have enough funds to assign this alias",

View file

@ -147,6 +147,12 @@
"TIME3": "1 hora",
"TIME4": "Nunca"
},
"SCALE": {
"75": "75% escala",
"100": "100% escala",
"125": "125% escala",
"150": "150% escala"
},
"MASTER_PASSWORD": {
"TITLE": "Atualizar password mestra",
"OLD": "Antiga password",
@ -194,7 +200,7 @@
"ASSIGN_ALIAS": {
"NAME": {
"LABEL": "Alias",
"PLACEHOLDER": "@ Introduzir alias",
"PLACEHOLDER": " Introduzir alias",
"TOOLTIP": "Um alias é uma forma abreviada da sua conta. Um alias só pode incluir letras, números e caracteres latinos “.” e “-”. Deve começar com “@”."
},
"COMMENT": {
@ -206,7 +212,7 @@
"BUTTON_ASSIGN": "Atribuir",
"FORM_ERRORS": {
"NAME_REQUIRED": "Nome é necessário",
"NAME_WRONG": "Alias tem nome errado",
"NAME_WRONG": "Nome inválido: símbolos permitidos \"0-9\", \"a-z\", \"-\", \".\"",
"NAME_LENGTH": "O alias deve ter entre 6 e 25 caracteres",
"NAME_EXISTS": "Nome de alias já existe",
"NO_MONEY": "Não tem fundos suficientes para atribuir esse alias",

View file

@ -147,6 +147,12 @@
"TIME3": "1 hour",
"TIME4": "Never"
},
"SCALE": {
"75": "75% scale",
"100": "100% scale",
"125": "125% scale",
"150": "150% scale"
},
"MASTER_PASSWORD": {
"TITLE": "Update master password",
"OLD": "Old password",
@ -194,7 +200,7 @@
"ASSIGN_ALIAS": {
"NAME": {
"LABEL": "Alias",
"PLACEHOLDER": "@ Enter alias",
"PLACEHOLDER": " Enter alias",
"TOOLTIP": "An alias is a shortened form or your account. An alias can only include Latin letters, numbers and characters “.” and “-”. It must start with “@”."
},
"COMMENT": {
@ -206,7 +212,7 @@
"BUTTON_ASSIGN": "Assign",
"FORM_ERRORS": {
"NAME_REQUIRED": "Name is required",
"NAME_WRONG": "Alias has wrong name",
"NAME_WRONG": "Invalid name: allowed symbols \"0-9\", \"a-z\", \"-\", \".\"",
"NAME_LENGTH": "The alias must be 6-25 characters long",
"NAME_EXISTS": "Alias name already exists",
"NO_MONEY": "You do not have enough funds to assign this alias",

View file

@ -147,6 +147,12 @@
"TIME3": "1 hour",
"TIME4": "Never"
},
"SCALE": {
"75": "75% scale",
"100": "100% scale",
"125": "125% scale",
"150": "150% scale"
},
"MASTER_PASSWORD": {
"TITLE": "Update master password",
"OLD": "Old password",
@ -194,7 +200,7 @@
"ASSIGN_ALIAS": {
"NAME": {
"LABEL": "Alias",
"PLACEHOLDER": "@ Enter alias",
"PLACEHOLDER": " Enter alias",
"TOOLTIP": "An alias is a shortened form or your account. An alias can only include Latin letters, numbers and characters “.” and “-”. It must start with “@”."
},
"COMMENT": {
@ -206,7 +212,7 @@
"BUTTON_ASSIGN": "Assign",
"FORM_ERRORS": {
"NAME_REQUIRED": "Name is required",
"NAME_WRONG": "Alias has wrong name",
"NAME_WRONG": "Invalid name: allowed symbols \"0-9\", \"a-z\", \"-\", \".\"",
"NAME_LENGTH": "The alias must be 6-25 characters long",
"NAME_EXISTS": "Alias name already exists",
"NO_MONEY": "You do not have enough funds to assign this alias",

View file

@ -147,6 +147,12 @@
"TIME3": "1 hour",
"TIME4": "Never"
},
"SCALE": {
"75": "75% scale",
"100": "100% scale",
"125": "125% scale",
"150": "150% scale"
},
"MASTER_PASSWORD": {
"TITLE": "Update master password",
"OLD": "Old password",
@ -194,7 +200,7 @@
"ASSIGN_ALIAS": {
"NAME": {
"LABEL": "Alias",
"PLACEHOLDER": "@ Enter alias",
"PLACEHOLDER": " Enter alias",
"TOOLTIP": "An alias is a shortened form or your account. An alias can only include Latin letters, numbers and characters “.” and “-”. It must start with “@”."
},
"COMMENT": {
@ -206,7 +212,7 @@
"BUTTON_ASSIGN": "Assign",
"FORM_ERRORS": {
"NAME_REQUIRED": "Name is required",
"NAME_WRONG": "Alias has wrong name",
"NAME_WRONG": "Invalid name: allowed symbols \"0-9\", \"a-z\", \"-\", \".\"",
"NAME_LENGTH": "The alias must be 6-25 characters long",
"NAME_EXISTS": "Alias name already exists",
"NO_MONEY": "You do not have enough funds to assign this alias",

View file

@ -147,6 +147,12 @@
"TIME3": "1 hour",
"TIME4": "Never"
},
"SCALE": {
"75": "75% scale",
"100": "100% scale",
"125": "125% scale",
"150": "150% scale"
},
"MASTER_PASSWORD": {
"TITLE": "Update master password",
"OLD": "Old password",
@ -194,7 +200,7 @@
"ASSIGN_ALIAS": {
"NAME": {
"LABEL": "Alias",
"PLACEHOLDER": "@ Enter alias",
"PLACEHOLDER": " Enter alias",
"TOOLTIP": "An alias is a shortened form or your account. An alias can only include Latin letters, numbers and characters “.” and “-”. It must start with “@”."
},
"COMMENT": {
@ -206,7 +212,7 @@
"BUTTON_ASSIGN": "Assign",
"FORM_ERRORS": {
"NAME_REQUIRED": "Name is required",
"NAME_WRONG": "Alias has wrong name",
"NAME_WRONG": "Invalid name: allowed symbols \"0-9\", \"a-z\", \"-\", \".\"",
"NAME_LENGTH": "The alias must be 6-25 characters long",
"NAME_EXISTS": "Alias name already exists",
"NO_MONEY": "You do not have enough funds to assign this alias",

View file

@ -147,6 +147,12 @@
"TIME3": "1 hour",
"TIME4": "Never"
},
"SCALE": {
"75": "75% scale",
"100": "100% scale",
"125": "125% scale",
"150": "150% scale"
},
"MASTER_PASSWORD": {
"TITLE": "Update master password",
"OLD": "Old password",
@ -194,7 +200,7 @@
"ASSIGN_ALIAS": {
"NAME": {
"LABEL": "Alias",
"PLACEHOLDER": "@ Enter alias",
"PLACEHOLDER": " Enter alias",
"TOOLTIP": "An alias is a shortened form or your account. An alias can only include Latin letters, numbers and characters “.” and “-”. It must start with “@”."
},
"COMMENT": {
@ -206,7 +212,7 @@
"BUTTON_ASSIGN": "Assign",
"FORM_ERRORS": {
"NAME_REQUIRED": "Name is required",
"NAME_WRONG": "Alias has wrong name",
"NAME_WRONG": "Invalid name: allowed symbols \"0-9\", \"a-z\", \"-\", \".\"",
"NAME_LENGTH": "The alias must be 6-25 characters long",
"NAME_EXISTS": "Alias name already exists",
"NO_MONEY": "You do not have enough funds to assign this alias",

View file

@ -147,6 +147,12 @@
"TIME3": "1 hour",
"TIME4": "Never"
},
"SCALE": {
"75": "75% scale",
"100": "100% scale",
"125": "125% scale",
"150": "150% scale"
},
"MASTER_PASSWORD": {
"TITLE": "Update master password",
"OLD": "Old password",
@ -194,7 +200,7 @@
"ASSIGN_ALIAS": {
"NAME": {
"LABEL": "Alias",
"PLACEHOLDER": "@ Enter alias",
"PLACEHOLDER": " Enter alias",
"TOOLTIP": "An alias is a shortened form or your account. An alias can only include Latin letters, numbers and characters “.” and “-”. It must start with “@”."
},
"COMMENT": {
@ -206,7 +212,7 @@
"BUTTON_ASSIGN": "Assign",
"FORM_ERRORS": {
"NAME_REQUIRED": "Name is required",
"NAME_WRONG": "Alias has wrong name",
"NAME_WRONG": "Invalid name: allowed symbols \"0-9\", \"a-z\", \"-\", \".\"",
"NAME_LENGTH": "The alias must be 6-25 characters long",
"NAME_EXISTS": "Alias name already exists",
"NO_MONEY": "You do not have enough funds to assign this alias",

View file

@ -147,6 +147,12 @@
"TIME3": "1 hour",
"TIME4": "Never"
},
"SCALE": {
"75": "75% scale",
"100": "100% scale",
"125": "125% scale",
"150": "150% scale"
},
"MASTER_PASSWORD": {
"TITLE": "Update master password",
"OLD": "Old password",
@ -194,7 +200,7 @@
"ASSIGN_ALIAS": {
"NAME": {
"LABEL": "Alias",
"PLACEHOLDER": "@ Enter alias",
"PLACEHOLDER": " Enter alias",
"TOOLTIP": "An alias is a shortened form or your account. An alias can only include Latin letters, numbers and characters “.” and “-”. It must start with “@”."
},
"COMMENT": {
@ -206,7 +212,7 @@
"BUTTON_ASSIGN": "Assign",
"FORM_ERRORS": {
"NAME_REQUIRED": "Name is required",
"NAME_WRONG": "Alias has wrong name",
"NAME_WRONG": "Invalid name: allowed symbols \"0-9\", \"a-z\", \"-\", \".\"",
"NAME_LENGTH": "The alias must be 6-25 characters long",
"NAME_EXISTS": "Alias name already exists",
"NO_MONEY": "You do not have enough funds to assign this alias",

View file

@ -147,6 +147,12 @@
"TIME3": "1 hour",
"TIME4": "Never"
},
"SCALE": {
"75": "75% scale",
"100": "100% scale",
"125": "125% scale",
"150": "150% scale"
},
"MASTER_PASSWORD": {
"TITLE": "Update master password",
"OLD": "Old password",
@ -194,7 +200,7 @@
"ASSIGN_ALIAS": {
"NAME": {
"LABEL": "Alias",
"PLACEHOLDER": "@ Enter alias",
"PLACEHOLDER": " Enter alias",
"TOOLTIP": "An alias is a shortened form or your account. An alias can only include Latin letters, numbers and characters “.” and “-”. It must start with “@”."
},
"COMMENT": {
@ -206,7 +212,7 @@
"BUTTON_ASSIGN": "Assign",
"FORM_ERRORS": {
"NAME_REQUIRED": "Name is required",
"NAME_WRONG": "Alias has wrong name",
"NAME_WRONG": "Invalid name: allowed symbols \"0-9\", \"a-z\", \"-\", \".\"",
"NAME_LENGTH": "The alias must be 6-25 characters long",
"NAME_EXISTS": "Alias name already exists",
"NO_MONEY": "You do not have enough funds to assign this alias",

View file

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 34 34" style="enable-background:new 0 0 34 34;" xml:space="preserve">
<style type="text/css">
.st0{fill:#4db1ff;}
</style>
<polygon class="st0" points="31.9,4.9 29.1,2.1 17,14.2 4.9,2.1 2.1,4.9 14.2,17 2.1,29.1 4.9,31.9 17,19.8 29.1,31.9 31.9,29.1
19.8,17 "/>
</svg>

After

Width:  |  Height:  |  Size: 549 B

View file

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 21.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="icons" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 384 384" style="enable-background:new 0 0 384 384;" xml:space="preserve">
<style type="text/css">
.st0{fill:#5cda9d;}
</style>
<path id="receive" class="st0" d="M64.2,309.6l58.2-210.4l48.1,71.6L178,182l12.7,4.7l81.9,30.4L64.2,309.6 M0,384l384-170.3
l-178.7-66.4L106.3,0L0,384L0,384z"/>
</svg>

After

Width:  |  Height:  |  Size: 573 B

View file

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 21.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="icons" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 384 384" style="enable-background:new 0 0 384 384;" xml:space="preserve">
<style type="text/css">
.st0{fill:#ff5252;}
</style>
<path id="send" class="st0" d="M319.8,74.4l-58.2,210.4l-48.1-71.6L206,202l-12.7-4.7l-81.9-30.4L319.8,74.4 M384,0L0,170.3
l178.7,66.4L277.7,384L384,0L384,0z"/>
</svg>

After

Width:  |  Height:  |  Size: 573 B

View file

@ -188,133 +188,4 @@ app-sidebar {
}
}
.sidebar-synchronization-status {
@include themify($themes) {
color: themed(optionalTextColor);
}
.status-container {
.offline:before {
@include themify($themes) {
background-color: themed(offlineColor);
}
}
.online:before {
@include themify($themes) {
background-color: themed(onlineColor);
}
}
.progress-bar-container {
.syncing {
.progress-bar {
@include themify($themes) {
background-color: themed(progressBarBackgroundColor);
}
.fill {
@include themify($themes) {
background-color: themed(progressBarFullBackgroundColor);
}
}
}
&.downloading {
.progress-bar {
@include themify($themes) {
background-color: themed(progressBarBackgroundColor);
}
.fill {
@include themify($themes) {
background-color: themed(blueTextColor);
}
}
}
}
}
.loading {
@include themify($themes) {
background-color: themed(progressBarFullBackgroundColor);
}
}
}
}
.update-container {
.standard {
@include themify($themes) {
color: themed(blueTextColor);
}
}
.important {
@include themify($themes) {
color: themed(orangeTextColor);
}
}
.critical {
@include themify($themes) {
color: themed(redTextColor);
}
}
.time {
@include themify($themes) {
color: themed(orangeTextColor);
}
}
.icon {
&.standard {
@include themify($themes) {
background-color: themed(blueTextColor);
}
}
&.important {
@include themify($themes) {
background-color: themed(orangeTextColor);
}
}
&.critical {
@include themify($themes) {
background-color: themed(redTextColor);
}
}
&.time {
@include themify($themes) {
background-color: themed(orangeTextColor);
}
}
}
}
}
}

View file

@ -0,0 +1,232 @@
.synchronization-status {
display: flex;
align-items: center;
justify-content: flex-start;
flex: 0 0 7rem;
font-size: 1.3rem;
@include themify($themes) {
color: themed(optionalTextColor);
}
.status-container {
position: relative;
flex-grow: 1;
text-align: left;
.offline, .online {
position: relative;
display: block;
line-height: 1.2rem;
padding-left: 2.2rem;
&:before {
content: '';
position: absolute;
top: 0;
left: 0;
border-radius: 50%;
width: 1.2rem;
height: 1.2rem;
}
}
.offline:before {
@include themify($themes) {
background-color: themed(offlineColor);
}
}
.online:before {
@include themify($themes) {
background-color: themed(onlineColor);
}
}
.syncing, .loading {
line-height: 5rem;
}
.progress-bar-container {
position: absolute;
bottom: 0;
left: 0;
height: 0.7rem;
width: 100%;
.syncing {
display: flex;
.progress-bar {
flex: 1 0 auto;
@include themify($themes) {
background-color: themed(progressBarBackgroundColor);
}
.fill {
height: 100%;
@include themify($themes) {
background-color: themed(progressBarFullBackgroundColor);
}
}
}
&.downloading {
.progress-bar {
@include themify($themes) {
background-color: themed(progressBarBackgroundColor);
}
.fill {
@include themify($themes) {
background-color: themed(blueTextColor);
}
}
}
}
.progress-percent {
flex: 0 0 auto;
font-size: 1.3rem;
line-height: 0.7rem;
padding-left: 0.7rem;
}
}
.loading {
@include themify($themes) {
background-color: themed(progressBarFullBackgroundColor);
}
animation: move 5s linear infinite;
background-image:
-webkit-gradient(
linear, 0 0, 100% 100%,
color-stop(.125, rgba(0, 0, 0, .15)), color-stop(.125, transparent),
color-stop(.250, transparent), color-stop(.250, rgba(0, 0, 0, .10)),
color-stop(.375, rgba(0, 0, 0, .10)), color-stop(.375, transparent),
color-stop(.500, transparent), color-stop(.500, rgba(0, 0, 0, .15)),
color-stop(.625, rgba(0, 0, 0, .15)), color-stop(.625, transparent),
color-stop(.750, transparent), color-stop(.750, rgba(0, 0, 0, .10)),
color-stop(.875, rgba(0, 0, 0, .10)), color-stop(.875, transparent),
to(transparent)
),
-webkit-gradient(
linear, 0 100%, 100% 0,
color-stop(.125, rgba(0, 0, 0, .30)), color-stop(.125, transparent),
color-stop(.250, transparent), color-stop(.250, rgba(0, 0, 0, .25)),
color-stop(.375, rgba(0, 0, 0, .25)), color-stop(.375, transparent),
color-stop(.500, transparent), color-stop(.500, rgba(0, 0, 0, .30)),
color-stop(.625, rgba(0, 0, 0, .30)), color-stop(.625, transparent),
color-stop(.750, transparent), color-stop(.750, rgba(0, 0, 0, .25)),
color-stop(.875, rgba(0, 0, 0, .25)), color-stop(.875, transparent),
to(transparent)
);
background-size: 7rem 7rem;
height: 100%;
}
}
}
.update-container {
display: flex;
flex-grow: 1;
margin-left: 1rem;
text-align: right;
.update-text {
flex: 1 1 auto;
font-size: 1.2rem;
line-height: 1.8rem;
text-align: left;
&.time {
font-size: 1.1rem;
}
}
.icon {
flex: 1 0 auto;
margin: 0.3rem 0 0 0.6rem;
width: 1.2rem;
height: 1.2rem;
&.update {
mask: url(./assets/icons/update.svg) no-repeat center;
}
&.time {
mask: url(./assets/icons/time.svg) no-repeat center;
}
}
.standard {
@include themify($themes) {
color: themed(blueTextColor);
}
}
.important {
@include themify($themes) {
color: themed(orangeTextColor);
}
}
.critical {
@include themify($themes) {
color: themed(redTextColor);
}
}
.time {
@include themify($themes) {
color: themed(orangeTextColor);
}
}
.icon {
&.standard {
@include themify($themes) {
background-color: themed(blueTextColor);
}
}
&.important {
@include themify($themes) {
background-color: themed(orangeTextColor);
}
}
&.critical {
@include themify($themes) {
background-color: themed(redTextColor);
}
}
&.time {
@include themify($themes) {
background-color: themed(orangeTextColor);
}
}
}
}
}
@keyframes move {
0% {
background-position: 100% -7rem;
}
100% {
background-position: 100% 7rem;
}
}

View file

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 34 34" style="enable-background:new 0 0 34 34;" xml:space="preserve">
<style type="text/css">
.st0{fill:#4db1ff;}
</style>
<polygon class="st0" points="31.9,4.9 29.1,2.1 17,14.2 4.9,2.1 2.1,4.9 14.2,17 2.1,29.1 4.9,31.9 17,19.8 29.1,31.9 31.9,29.1
19.8,17 "/>
</svg>

After

Width:  |  Height:  |  Size: 549 B

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -5800,8 +5800,8 @@ __webpack_require__.r(__webpack_exports__);
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
__webpack_require__(/*! /var/www/zano-project/zano/src/gui/qt-daemon/html_source/src/polyfills.ts */"./src/polyfills.ts");
module.exports = __webpack_require__(/*! /var/www/zano-project/zano/src/gui/qt-daemon/html_source/node_modules/@angular-devkit/build-angular/src/angular-cli-files/models/jit-polyfills.js */"./node_modules/@angular-devkit/build-angular/src/angular-cli-files/models/jit-polyfills.js");
__webpack_require__(/*! /Users/mekasan/Projects/Projects/zano_v1/src/gui/qt-daemon/html_source/src/polyfills.ts */"./src/polyfills.ts");
module.exports = __webpack_require__(/*! /Users/mekasan/Projects/Projects/zano_v1/src/gui/qt-daemon/html_source/node_modules/@angular-devkit/build-angular/src/angular-cli-files/models/jit-polyfills.js */"./node_modules/@angular-devkit/build-angular/src/angular-cli-files/models/jit-polyfills.js");
/***/ })

View file

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 21.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="icons" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 384 384" style="enable-background:new 0 0 384 384;" xml:space="preserve">
<style type="text/css">
.st0{fill:#5cda9d;}
</style>
<path id="receive" class="st0" d="M64.2,309.6l58.2-210.4l48.1,71.6L178,182l12.7,4.7l81.9,30.4L64.2,309.6 M0,384l384-170.3
l-178.7-66.4L106.3,0L0,384L0,384z"/>
</svg>

After

Width:  |  Height:  |  Size: 573 B

View file

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 21.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="icons" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 384 384" style="enable-background:new 0 0 384 384;" xml:space="preserve">
<style type="text/css">
.st0{fill:#ff5252;}
</style>
<path id="send" class="st0" d="M319.8,74.4l-58.2,210.4l-48.1-71.6L206,202l-12.7-4.7l-81.9-30.4L319.8,74.4 M384,0L0,170.3
l178.7,66.4L277.7,384L384,0L384,0z"/>
</svg>

After

Width:  |  Height:  |  Size: 573 B

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

View file

@ -32,6 +32,7 @@
"highcharts": "^7.0.3",
"idlejs": "^2.0.1",
"json-bignumber": "^1.0.1",
"lodash": "^4.17.20",
"ngx-contextmenu": "^5.1.1",
"ngx-papaparse": "^3.0.3",
"qrcode": "^1.3.0",

View file

@ -3,6 +3,8 @@ import {Transaction} from '../../models/transaction.model';
import {VariablesService} from '../../services/variables.service';
import {BackendService} from '../../services/backend.service';
import {IntToMoneyPipe} from '../../pipes/int-to-money.pipe';
import {BLOCK_EXPLORER_TX_URL_PREFIX} from '../../../_shared/constants';
import {BLOCK_EXPLORER_TN_TX_URL_PREFIX} from '../../../_shared/constants';
@Component({
selector: 'app-transaction-details',
@ -32,7 +34,7 @@ export class TransactionDetailsComponent implements OnInit, OnDestroy {
}
openInBrowser(tr) {
this.backendService.openUrlInBrowser('explorer.zano.org/transaction/' + tr);
this.backendService.openUrlInBrowser((this.variablesService.testnet ? BLOCK_EXPLORER_TN_TX_URL_PREFIX : BLOCK_EXPLORER_TX_URL_PREFIX)+ tr);
}
ngOnDestroy() {}

View file

@ -3,6 +3,9 @@ import {Transaction} from './transaction.model';
import {BigNumber} from 'bignumber.js';
export class Wallet {
stop_paginate: boolean;
open_from_exist: boolean;
updated = false;
wallet_id: number;
name: string;
pass: string;
@ -14,6 +17,7 @@ export class Wallet {
tracking_hey: string;
is_auditable: boolean;
is_watch_only: boolean;
exclude_mining_txs: boolean;
alias_available: boolean;
alias?: object;
@ -101,7 +105,7 @@ export class Wallet {
prepareHistory(items: Transaction[]): void {
for (let i = 0; i < items.length; i++) {
if ((items[i].tx_type === 7 && items[i].is_income) || (items[i].tx_type === 11 && items[i].is_income) || (items[i].amount.eq(0) && items[i].fee.eq(0))) {
if ((items[i].tx_type === 7 && items[i].is_income) || (items[i].tx_type === 11 && items[i].is_income) || (items[i].amount.eq(0) && items[i].fee.eq(0) && !items[i].is_mining)) {
let exists = false;
for (let j = 0; j < this.excluded_history.length; j++) {
if (this.excluded_history[j].tx_hash === items[i].tx_hash) {

View file

@ -56,45 +56,38 @@ export class BackendService {
switch (error) {
case 'NOT_ENOUGH_MONEY':
error_translate = 'ERRORS.NOT_ENOUGH_MONEY';
// error_translate = 'ERRORS.NO_MONEY'; maybe that one?
if (command === 'cancel_offer') {
error_translate = this.translate.instant('ERRORS.NO_MONEY_REMOVE_OFFER', {
'fee': this.variablesService.default_fee,
'currency': this.variablesService.defaultCurrency
});
}
break;
case 'CORE_BUSY':
if (command !== 'get_all_aliases') {
error_translate = 'ERRORS.CORE_BUSY';
}
error_translate = 'ERRORS.CORE_BUSY';
break;
case 'BUSY':
error_translate = 'ERRORS.DAEMON_BUSY';
break;
case 'OVERFLOW':
if (command !== 'get_all_aliases') {
error_translate = '';
}
break;
case 'INTERNAL_ERROR:daemon is busy':
error_translate = 'ERRORS.DAEMON_BUSY';
break;
case 'INTERNAL_ERROR:not enough money':
case 'INTERNAL_ERROR:NOT_ENOUGH_MONEY':
if (command === 'cancel_offer') {
error_translate = this.translate.instant('ERRORS.NO_MONEY_REMOVE_OFFER', {
'fee': this.variablesService.default_fee,
'currency': this.variablesService.defaultCurrency
});
} else {
error_translate = 'ERRORS.NO_MONEY';
}
break;
case 'NOT_ENOUGH_OUTPUTS_FOR_MIXING':
case 'INTERNAL_ERROR:not enough outputs to mix':
error_translate = 'ERRORS.NOT_ENOUGH_OUTPUTS_TO_MIX';
break;
case 'INTERNAL_ERROR:transaction is too big':
case 'TX_IS_TOO_BIG':
error_translate = 'ERRORS.TRANSACTION_IS_TO_BIG';
break;
case 'INTERNAL_ERROR:Transfer attempt while daemon offline':
case 'DISCONNECTED':
error_translate = 'ERRORS.TRANSFER_ATTEMPT';
break;
case 'ACCESS_DENIED':
error_translate = 'ERRORS.ACCESS_DENIED';
break;
case 'INTERNAL_ERROR:transaction was rejected by daemon':
case 'TX_REJECTED':
// if (command === 'request_alias_registration') {
// error_translate = 'INFORMER.ALIAS_IN_REGISTER';
// } else {
@ -114,7 +107,6 @@ export class BackendService {
error_translate = 'ERRORS.WALLET_WATCH_ONLY_NOT_SUPPORTED';
break;
case 'WRONG_PASSWORD':
case 'WRONG_PASSWORD:invalid password':
params = JSON.parse(params);
if (!params.testEmpty) {
error_translate = 'ERRORS.WRONG_PASSWORD';
@ -154,6 +146,9 @@ export class BackendService {
case 'ALREADY_EXISTS':
error_translate = 'ERRORS.FILE_EXIST';
break;
case 'FAILED':
BackendService.Debug(0, `Error: (${error}) was triggered by command: ${command}`);
break;
default:
error_translate = error;
}
@ -163,6 +158,7 @@ export class BackendService {
if (error.indexOf('FAILED:failed to open binary wallet file for saving') > -1 && command === 'generate_wallet') {
error_translate = '';
}
if (error_translate !== '') {
this.modalService.prepareModal('error', error_translate);
}
@ -202,6 +198,7 @@ export class BackendService {
};
}
const core_busy = Result.error_code === 'CORE_BUSY';
const Status = (Result.error_code === 'OK' || Result.error_code === 'TRUE');
if (!Status && Status !== undefined && Result.error_code !== undefined) {
@ -211,24 +208,44 @@ export class BackendService {
let res_error_code = false;
if (typeof Result === 'object' && 'error_code' in Result && Result.error_code !== 'OK' && Result.error_code !== 'TRUE' && Result.error_code !== 'FALSE') {
this.informerRun(Result.error_code, params, command);
res_error_code = Result.error_code;
if (core_busy) {
setTimeout( () => {
// this is will avoid update data when user
// on other wallet after CORE_BUSY (blink of data)
if (command !== 'get_recent_transfers') {
this.runCommand(command, params, callback);
} else {
const current_wallet_id = this.variablesService.currentWallet.wallet_id;
if (current_wallet_id === params.wallet_id) {
this.runCommand(command, params, callback);
}
}
}, 50);
} else {
this.informerRun(Result.error_code, params, command);
res_error_code = Result.error_code;
}
}
// if ( command === 'get_offers_ex' ){
// Service.printLog( "get_offers_ex offers count "+((data.offers)?data.offers.length:0) );
// }
if (typeof callback === 'function') {
callback(Status, data, res_error_code);
} else {
return data;
if (!core_busy) {
if (typeof callback === 'function') {
callback(Status, data, res_error_code);
} else {
return data;
}
}
}
private runCommand(command, params?, callback?) {
if (this.backendObject) {
if (command === 'get_recent_transfers') {
this.variablesService.get_recent_transfers = true;
}
const Action = this.backendObject[command];
if (!Action) {
BackendService.Debug(0, 'Run Command Error! Command "' + command + '" don\'t found in backendObject');
@ -236,6 +253,9 @@ export class BackendService {
const that = this;
params = (typeof params === 'string') ? params : JSONBigNumber.stringify(params);
if (params === undefined || params === '{}') {
if (command === 'get_recent_transfers') {
this.variablesService.get_recent_transfers = false;
}
Action(function (resultStr) {
that.commandDebug(command, params, resultStr);
return that.backendCallback(resultStr, params, callback, command);
@ -636,13 +656,14 @@ export class BackendService {
}
}
getRecentTransfers( id, offset, count, callback) {
getRecentTransfers( id, offset, count, exclude_mining_txs, callback) {
const params = {
wallet_id: id,
offset: offset,
count: count
count: count,
exclude_mining_txs: exclude_mining_txs
};
this.runCommand('get_recent_transfers', params, callback);
this.runCommand('get_recent_transfers', params, callback);
}
getPoolInfo(callback) {
@ -651,7 +672,9 @@ export class BackendService {
getVersion(callback) {
this.runCommand('get_version', {}, (status, version) => {
callback(version);
this.runCommand('get_network_type', {}, (status, type) => {
callback(version, type);
});
});
}

View file

@ -1,24 +1,26 @@
import { Injectable, NgZone } from '@angular/core';
import { VariablesService } from './variables.service';
import { PaginationStore } from './pagination.store';
import * as _ from 'lodash';
import {Store} from 'store';
@Injectable({
providedIn: 'root'
providedIn: 'root',
})
export class PaginationService {
constructor(
private variables: VariablesService,
private ngZone: NgZone
private ngZone: NgZone,
private paginationStore: PaginationStore,
) { }
paginate(currentPage = 1) {
if (currentPage < 1) {
currentPage = 1;
} else if (currentPage > this.variables.currentWallet.totalPages) {
currentPage = this.variables.currentWallet.totalPages;
}
let startPage: number, endPage: number;
if (this.variables.currentWallet.totalPages <= this.variables.maxPages) {
startPage = 1;
@ -44,4 +46,57 @@ export class PaginationService {
this.variables.currentWallet.pages = Array.from(Array((endPage + 1) - startPage).keys()).map(i => startPage + i);
});
}
getOffset(walletID) {
const mining = this.variables.currentWallet.exclude_mining_txs;
const currentPage = (this.variables.currentWallet.currentPage);
let offset = ((currentPage - 1) * this.variables.count);
if (!mining) { return offset; }
const value = this.paginationStore.value;
const pages = value.filter(item => item.walletID === walletID);
if (pages && pages.length) {
const max = _.maxBy(pages, 'page');
const isForward = this.paginationStore.isForward(pages, currentPage);
if (isForward) {
offset = max.offset;
} else {
const index = pages.findIndex(item => item.page === (currentPage));
offset = pages[index].offset;
}
}
return offset;
}
calcPages(data) {
if (data.total_history_items && (data && data.history)) {
this.variables.currentWallet.totalPages = Math.ceil( data.total_history_items / this.variables.count);
this.variables.currentWallet.totalPages > this.variables.maxPages
? this.variables.currentWallet.pages = new Array(5).fill(1).map((value, index) => value + index)
: this.variables.currentWallet.pages =
new Array(this.variables.currentWallet.totalPages).fill(1).map((value, index) => value + index);
} else if (this.variables.currentWallet.restore) {
this.variables.currentWallet.totalPages = Math.ceil( data.history.length / this.variables.count);
this.variables.currentWallet.totalPages > this.variables.maxPages
? this.variables.currentWallet.pages = new Array(5).fill(1).map((value, index) => value + index)
: this.variables.currentWallet.pages =
new Array(this.variables.currentWallet.totalPages).fill(1).map((value, index) => value + index);
}
}
prepareHistory(data, status) {
if (status && (data && data.total_history_items)) {
this.variables.currentWallet.history.splice(0, this.variables.currentWallet.history.length);
this.ngZone.run(() => {
this.paginate(this.variables.currentWallet.currentPage);
if (data.history.length !== 0) {
this.variables.currentWallet.restore = false;
this.variables.currentWallet.total_history_item = data.total_history_items;
this.variables.currentWallet.prepareHistory(data.history);
if (this.variables.currentWallet.currentPage === 1 && data.unconfirmed) {
this.variables.currentWallet.prepareHistory(data.unconfirmed);
}
}
});
}
}
}

View file

@ -0,0 +1,36 @@
import {Injectable} from '@angular/core';
import {Observable, BehaviorSubject} from 'rxjs';
import * as _ from 'lodash';
export interface Pages {
page: number;
offset: number;
walletID: number;
}
@Injectable({
providedIn: 'root'
})
export class PaginationStore {
constructor(
) {}
private subject = new BehaviorSubject<Pages[]>(null);
pages$: Observable<Pages[]> = this.subject.asObservable();
isForward(pages, currentPage) {
const max = _.maxBy(pages, 'page');
return !max || max.page < currentPage || max.page === currentPage;
}
setPage(pageNumber: number, offset: number, walletID: number) {
let newPages: Pages[] = [];
const pages = this.subject.getValue();
if (pages && pages.length) {
newPages = pages.slice(0);
}
newPages.push({page: pageNumber, offset, walletID});
this.subject.next(newPages);
}
get value() {
return this.subject.value;
}
}

View file

@ -0,0 +1,14 @@
import {Injectable} from '@angular/core';
@Injectable()
export class UtilsService {
getMinWidthByScale(scale: number) {
switch (scale) {
case 7.5 : return 900;
case 10 : return 1200;
case 12.5 : return 1500;
case 15 : return 1800;
default : return 1200;
}
}
}

View file

@ -11,7 +11,9 @@ import {BigNumber} from 'bignumber.js';
providedIn: 'root'
})
export class VariablesService {
public request_on_in = {};
public stop_paginate = {};
public sync_started = false;
public digits = 12;
public appPass = '';
public appLogin = false;
@ -36,6 +38,7 @@ export class VariablesService {
progress_value: 0,
progress_value_text: '0'
};
public get_recent_transfers = false; // avoid of execute function before collback complete
public default_fee = '0.010000000000';
public default_fee_big = new BigNumber('10000000000');
@ -54,6 +57,9 @@ export class VariablesService {
public count = 40;
public maxPages = 5;
public testnet = false;
public networkType = ''; // testnet of mainnet
public wallets: Array<Wallet> = [];
public currentWallet: Wallet;
public selectWallet: number;
@ -68,7 +74,7 @@ export class VariablesService {
public newContact: Contact = {name: null, address: null, notes: null};
public pattern = '^[a-zA-Z0-9_.\\\]\*\|\~\!\?\@\#\$\%\^\&\+\{\}\(\)\<\>\:\;\"\'\-\=\/\,\[\\\\]*$';
public after_sync_request: any = {};
getExpMedTsEvent = new BehaviorSubject(null);
getHeightAppEvent = new BehaviorSubject(null);
getHeightMaxEvent = new BehaviorSubject(null);
@ -159,6 +165,15 @@ export class VariablesService {
return null;
}
getNotLoadedWallet() {
for (let i = 0; i < this.wallets.length; i++) {
if (!this.wallets[i].loaded) {
return this.wallets[i];
}
}
return null;
}
startCountdown() {
this.idle.within(this.settings.appLockTime).start();
}

View file

@ -1,3 +1,10 @@
export const MIXIN: number = 10;
export const AUDITABLE_WALLET_HELP_PAGE: string = 'docs.zano.org/docs/auditable-wallets';
export const RCV_ADDR_QR_SCALE: number = 2;
export const MIXIN: number = 10; // default mixin value
export const RCV_ADDR_QR_SCALE: number = 2; // scale factor for QR code
export const AUDITABLE_WALLET_HELP_PAGE: string = 'docs.zano.org/docs/auditable-wallets';
export const CREATE_NEW_WALLET_HELP_PAGE: string = 'docs.zano.org/docs/getting-started-1#section-create-new-wallet';
export const LOCKED_BALANCE_HELP_PAGE: string = 'docs.zano.org/docs/locked-balance';
export const DOWNLOADS_PAGE_URL: string = 'zano.org/downloads.html';
export const BLOCK_EXPLORER_TX_URL_PREFIX: string = 'explorer.zano.org/transaction/';
export const BLOCK_EXPLORER_TN_TX_URL_PREFIX: string = 'testnet-explorer.zano.org/transaction/';

View file

@ -14,6 +14,7 @@ import { ActivatedRoute } from '@angular/router';
export class AddContactsComponent implements OnInit, OnDestroy {
id: number;
queryRouting;
isModalDialogVisible;
addContactForm = new FormGroup({
address: new FormControl('', [
Validators.required,

View file

@ -8,14 +8,17 @@ import {ContextMenuComponent} from 'ngx-contextmenu';
import {IntToMoneyPipe} from './_helpers/pipes/int-to-money.pipe';
import {BigNumber} from 'bignumber.js';
import {ModalService} from './_helpers/services/modal.service';
import {UtilsService} from './_helpers/services/utils.service';
import {Store} from 'store';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
styleUrls: ['./app.component.scss'],
providers: [UtilsService]
})
export class AppComponent implements OnInit, OnDestroy {
intervalUpdatePriceState;
intervalUpdateContractsState;
expMedTsEvent;
@ -37,7 +40,9 @@ export class AppComponent implements OnInit, OnDestroy {
public variablesService: VariablesService,
private ngZone: NgZone,
private intToMoneyPipe: IntToMoneyPipe,
private modalService: ModalService
private modalService: ModalService,
private utilsService: UtilsService,
private store: Store
) {
translate.addLangs(['en', 'fr', 'de', 'it', 'pt']);
translate.setDefaultLang('en');
@ -126,7 +131,6 @@ export class AppComponent implements OnInit, OnDestroy {
const wallet_state = data.wallet_state;
const is_mining = data.is_mining;
const wallet = this.variablesService.getWallet(data.wallet_id);
// 1-synch, 2-ready, 3 - error
if (wallet) {
this.ngZone.run(() => {
@ -154,21 +158,15 @@ export class AppComponent implements OnInit, OnDestroy {
if (wallet) {
this.ngZone.run(() => {
wallet.progress = (data.progress < 0) ? 0 : ((data.progress > 100) ? 100 : data.progress);
if (!this.variablesService.sync_started) {
this.variablesService.sync_started = true;
}
this.addToStore(wallet, true); // subscribe on data
if (wallet.progress === 0) {
wallet.loaded = false;
} else if (wallet.progress === 100) {
wallet.loaded = true;
if (wallet.total_history_item) {
wallet.totalPages = Math.ceil( wallet.total_history_item / this.variablesService.count);
wallet.totalPages > this.variablesService.maxPages
? wallet.pages = new Array(5).fill(1).map((value, index) => value + index)
: wallet.pages = new Array(wallet.totalPages).fill(1).map((value, index) => value + index);
} else if (wallet.restore) {
wallet.totalPages = Math.ceil( wallet.history.length / this.variablesService.count);
wallet.totalPages > this.variablesService.maxPages
? wallet.pages = new Array(5).fill(1).map((value, index) => value + index)
: wallet.pages = new Array(wallet.totalPages).fill(1).map((value, index) => value + index);
}
this.addToStore(wallet, false);
}
});
}
@ -248,6 +246,9 @@ export class AppComponent implements OnInit, OnDestroy {
const wallet = this.variablesService.getWallet(wallet_id);
if (wallet) {
if(wallet.history.length > 40) {
wallet.history.splice(40, 1);
}
this.ngZone.run(() => {
if (!wallet.loaded) {
@ -550,6 +551,9 @@ export class AppComponent implements OnInit, OnDestroy {
this.renderer.addClass(document.body, 'theme-' + this.variablesService.defaultTheme);
}
if (this.variablesService.settings.hasOwnProperty('scale') && [7.5, 10, 12.5, 15].indexOf(this.variablesService.settings.scale) !== -1) {
const width = this.utilsService.getMinWidthByScale(this.variablesService.settings.scale);
const app = document.documentElement.querySelector('app-root');
this.renderer.setStyle(app, 'min-width', width + 'px');
this.renderer.setStyle(document.documentElement, 'font-size', this.variablesService.settings.scale + 'px');
}
} else {
@ -713,6 +717,28 @@ export class AppComponent implements OnInit, OnDestroy {
}
}
addToStore(wallet, boolean) {
const value = this.store.value.sync;
if (value && value.length) {
const sync = value.filter(item => item.wallet_id === wallet.wallet_id);
if (sync && sync.length) {
const result = value.map(item => {
if (item.wallet_id === wallet.wallet_id) {
return {sync: boolean, wallet_id: wallet.wallet_id};
} else {
return item;
}
});
this.store.set('sync', result);
} else {
value.push({sync: boolean, wallet_id: wallet.wallet_id});
this.store.set('sync', value);
}
} else {
this.store.set('sync', [{sync: boolean, wallet_id: wallet.wallet_id}]);
}
}
ngOnDestroy() {
if (this.intervalUpdateContractsState) {
clearInterval(this.intervalUpdateContractsState);

View file

@ -32,9 +32,16 @@ import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
import { TranslateHttpLoader } from '@ngx-translate/http-loader';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { NgSelectModule } from '@ng-select/ng-select';
// SERVICES
import { BackendService } from './_helpers/services/backend.service';
import { ModalService } from './_helpers/services/modal.service';
import { PaginationStore } from './_helpers/services/pagination.store';
// SERVICES
// Feature module
import { Store } from 'store';
// Feature module
import { MoneyToIntPipe } from './_helpers/pipes/money-to-int.pipe';
import { IntToMoneyPipe } from './_helpers/pipes/int-to-money.pipe';
import { HistoryTypeMessagesPipe } from './_helpers/pipes/history-type-messages.pipe';
@ -144,8 +151,10 @@ export function highchartsFactory() {
ContextMenuModule.forRoot()
],
providers: [
Store,
BackendService,
ModalService,
PaginationStore,
MoneyToIntPipe,
IntToMoneyPipe,
{ provide: HIGHCHARTS_MODULES, useFactory: highchartsFactory }

View file

@ -17,7 +17,9 @@
<label for="alias-name" tooltip="{{ 'ASSIGN_ALIAS.NAME.TOOLTIP' | translate }}" placement="bottom-left" tooltipClass="table-tooltip assign-alias-tooltip" [delay]="50">
{{ 'ASSIGN_ALIAS.NAME.LABEL' | translate }}
</label>
<input type="text" id="alias-name" formControlName="name" placeholder="{{ 'ASSIGN_ALIAS.NAME.PLACEHOLDER' | translate }}" (contextmenu)="variablesService.onContextMenu($event)">
<div class="has-no-edit-symbol">
<input type="text" id="alias-name" formControlName="name" placeholder="{{ 'ASSIGN_ALIAS.NAME.PLACEHOLDER' | translate }}" (contextmenu)="variablesService.onContextMenu($event)">
</div>
<div class="error-block" *ngIf="assignForm.controls['name'].invalid && (assignForm.controls['name'].dirty || assignForm.controls['name'].touched)">
<div *ngIf="assignForm.controls['name'].errors['required']">
{{ 'ASSIGN_ALIAS.FORM_ERRORS.NAME_REQUIRED' | translate }}

View file

@ -28,3 +28,19 @@
padding: 1rem 1.5rem;
max-width: 46rem;
}
.has-no-edit-symbol {
position: relative;
width: 100%;
input {
padding-left: 2.35rem;
}
&:after {
content: '@';
position: absolute;
display: inline-block;
top: 50%;
left: 1rem;
transform: translateY(-50%);
}
}

View file

@ -47,7 +47,7 @@ export class AssignAliasComponent implements OnInit, OnDestroy {
private location: Location,
private router: Router,
private backend: BackendService,
private variablesService: VariablesService,
public variablesService: VariablesService,
private modalService: ModalService,
private moneyToInt: MoneyToIntPipe,
private intToMoney: IntToMoneyPipe

View file

@ -16,7 +16,7 @@ export class ContactSendComponent implements OnInit, OnDestroy {
constructor(
private location: Location,
private variablesService: VariablesService,
public variablesService: VariablesService,
private route: ActivatedRoute
) { }

View file

@ -14,7 +14,7 @@ export class ContactsComponent implements OnInit {
constructor(
private location: Location,
private variablesService: VariablesService,
public variablesService: VariablesService,
private backend: BackendService
) {}

View file

@ -40,7 +40,7 @@ export class CreateWalletComponent implements OnInit {
constructor(
private router: Router,
private backend: BackendService,
private variablesService: VariablesService,
public variablesService: VariablesService,
private modalService: ModalService,
private ngZone: NgZone,
private translate: TranslateService

View file

@ -23,7 +23,7 @@ export class EditAliasComponent implements OnInit {
private location: Location,
private router: Router,
private backend: BackendService,
private variablesService: VariablesService,
public variablesService: VariablesService,
private modalService: ModalService,
private ngZone: NgZone
) {}

View file

@ -64,16 +64,30 @@
}
&.send {
.status-transaction {
mask: url(../../assets/icons/send.svg) no-repeat center;
background-color: transparent;
}
.status-transaction::after {
display: block;
content:'';
background:url("../../assets/icons/send-red.svg") no-repeat center;
width: 13px;
height: 13px;
}
}
&.received {
.status-transaction {
mask: url(../../assets/icons/receive.svg) no-repeat center;
background-color: transparent;
}
.status-transaction::after {
display: block;
content:'';
background:url("../../assets/icons/receive-green.svg") no-repeat center;
width: 13px;
height: 13px;
}
}
}

View file

@ -43,10 +43,84 @@
<div class="wrap-button">
<button type="submit" class="blue-button">{{ 'LOGIN.BUTTON_NEXT' | translate }}</button>
<button type="button" class="blue-button_reset" (click)="dropSecureAppData()">{{ 'LOGIN.BUTTON_RESET' | translate }}</button> <!--Add "Reset"-button-->
</div>
</div>
</form>
</div>
</div>
<div class="synchronization-status" [ngStyle]="{'align-items': variablesService.daemon_state === 1 || variablesService.daemon_state === 6 ? 'flex-start' : 'center'}">
<div class="status-container">
<span class="offline" *ngIf="variablesService.daemon_state === 0">
{{ 'SIDEBAR.SYNCHRONIZATION.OFFLINE' | translate }}
</span>
<span class="syncing" *ngIf="variablesService.daemon_state === 1">
{{ 'SIDEBAR.SYNCHRONIZATION.SYNCING' | translate }} {{ variablesService.height_app }}{{ 'SIDEBAR.SYNCHRONIZATION.SLASH' | translate }}{{ variablesService.height_max }}
</span>
<span class="online" *ngIf="variablesService.daemon_state === 2">
{{ 'SIDEBAR.SYNCHRONIZATION.ONLINE' | translate }}
</span>
<span class="loading" *ngIf="variablesService.daemon_state === 3">
{{ 'SIDEBAR.SYNCHRONIZATION.LOADING' | translate }}
</span>
<span class="offline" *ngIf="variablesService.daemon_state === 4">
{{ 'SIDEBAR.SYNCHRONIZATION.ERROR' | translate }}
</span>
<span class="online" *ngIf="variablesService.daemon_state === 5">
{{ 'SIDEBAR.SYNCHRONIZATION.COMPLETE' | translate }}
</span>
<span class="syncing" *ngIf="variablesService.daemon_state === 6">
{{ 'SIDEBAR.SYNCHRONIZATION.DOWNLOADING' | translate }} {{ variablesService.downloaded }}{{ 'SIDEBAR.SYNCHRONIZATION.SLASH' | translate }}{{ variablesService.total }}{{ 'SIDEBAR.SYNCHRONIZATION.MB' | translate }}
</span>
<div class="progress-bar-container" *ngIf="variablesService.daemon_state === 1 || variablesService.daemon_state === 3">
<div class="syncing" *ngIf="variablesService.daemon_state === 1">
<div class="progress-bar">
<div class="fill" [style.width]="variablesService.sync.progress_value + '%'"></div>
</div>
<div class="progress-percent">{{ variablesService.sync.progress_value_text }}%</div>
</div>
<div class="loading" *ngIf="variablesService.daemon_state === 3"></div>
</div>
<div class="progress-bar-container" *ngIf="variablesService.daemon_state === 6">
<div class="syncing downloading" *ngIf="variablesService.daemon_state === 6">
<div class="progress-bar">
<div class="fill" [style.width]="variablesService.download.progress_value + '%'"></div>
</div>
<div class="progress-percent">{{ variablesService.download.progress_value_text }}%</div>
</div>
</div>
</div>
<div class="update-container" *ngIf="(variablesService.daemon_state === 0 || variablesService.daemon_state === 2) && [2, 3, 4].indexOf(variablesService.last_build_displaymode) !== -1">
<ng-container *ngIf="variablesService.last_build_displaymode === 2">
<div class="update-text standard">
<span [style.cursor]="'pointer'" (click)="getUpdate()">{{ 'SIDEBAR.UPDATE.STANDARD' | translate }}</span>
</div>
<i class="icon update standard" tooltip="{{ 'SIDEBAR.UPDATE.STANDARD_TOOLTIP' | translate }}" placement="right-bottom" tooltipClass="update-tooltip" [delay]="500"></i>
</ng-container>
<ng-container *ngIf="variablesService.last_build_displaymode === 3">
<div class="update-text important">
<span [style.cursor]="'pointer'" (click)="getUpdate()">{{ 'SIDEBAR.UPDATE.IMPORTANT' | translate }}</span>
<br>
<span style="font-size: 1rem">{{ 'SIDEBAR.UPDATE.IMPORTANT_HINT' | translate }}</span>
</div>
<i class="icon update important" tooltip="{{ 'SIDEBAR.UPDATE.IMPORTANT_TOOLTIP' | translate }}" placement="right-bottom" tooltipClass="update-tooltip important" [delay]="500"></i>
</ng-container>
<ng-container *ngIf="variablesService.last_build_displaymode === 4">
<div class="update-text critical">
<span [style.cursor]="'pointer'" (click)="getUpdate()">{{ 'SIDEBAR.UPDATE.CRITICAL' | translate }}</span>
<br>
<span style="font-size: 1rem">{{ 'SIDEBAR.UPDATE.IMPORTANT_HINT' | translate }}</span>
</div>
<i class="icon update critical" tooltip="{{ 'SIDEBAR.UPDATE.CRITICAL_TOOLTIP' | translate }}" placement="right-bottom" tooltipClass="update-tooltip critical" [delay]="500"></i>
</ng-container>
</div>
<div class="update-container" *ngIf="variablesService.daemon_state === 2 && variablesService.net_time_delta_median !== 0">
<div class="update-text time">
<span>{{ 'SIDEBAR.UPDATE.TIME' | translate }}</span>
</div>
<i class="icon time" tooltip="{{ 'SIDEBAR.UPDATE.TIME_TOOLTIP' | translate }}" placement="right-bottom" tooltipClass="update-tooltip important" [delay]="500"></i>
</div>
</div>
</div>

View file

@ -45,3 +45,8 @@
}
}
}
.synchronization-status {
position: absolute;
bottom: 3rem;
left: 3rem;
}

View file

@ -5,6 +5,7 @@ import {BackendService} from '../_helpers/services/backend.service';
import {VariablesService} from '../_helpers/services/variables.service';
import {ModalService} from '../_helpers/services/modal.service';
import {Wallet} from '../_helpers/models/wallet.model';
import {DOWNLOADS_PAGE_URL} from '../_shared/constants'
import icons from '../../assets/icons/icons.json';
@ -101,7 +102,7 @@ export class LoginComponent implements OnInit, OnDestroy {
this.variablesService.startCountdown();
}
this.ngZone.run(() => {
this.router.navigate(['/']);
this.router.navigate(['/'], {queryParams: {prevUrl: 'login'}});
});
}
});
@ -186,6 +187,7 @@ export class LoginComponent implements OnInit, OnDestroy {
new_wallet.is_auditable = open_data['wi'].is_auditable;
new_wallet.is_watch_only = open_data['wi'].is_watch_only;
new_wallet.currentPage = 1;
new_wallet.exclude_mining_txs = false;
if (open_data.recent_history && open_data.recent_history.history) {
new_wallet.total_history_item = open_data.recent_history.total_history_items;
new_wallet.totalPages = Math.ceil( open_data.recent_history.total_history_items / this.variablesService.count);
@ -232,6 +234,9 @@ export class LoginComponent implements OnInit, OnDestroy {
});
}
getUpdate() {
this.backend.openUrlInBrowser(DOWNLOADS_PAGE_URL);
}
ngOnDestroy() {
this.queryRouting.unsubscribe();

View file

@ -1,6 +1,6 @@
<div class="content">
<div class="head" *ngIf="variablesService.wallets.length > 0">
<div class="head" *ngIf="variablesService.wallets.length > 0 && prevUrl !== 'login'">
<button type="button" class="back-btn" (click)="back()">
<i class="icon back"></i>
<span>{{ 'COMMON.BACK' | translate }}</span>

View file

@ -2,8 +2,9 @@ import {Component, NgZone, OnInit} from '@angular/core';
import {Location} from '@angular/common';
import {BackendService} from '../_helpers/services/backend.service';
import {VariablesService} from '../_helpers/services/variables.service';
import {Router} from '@angular/router';
import {ActivatedRoute, Router} from '@angular/router';
import {TranslateService} from '@ngx-translate/core';
import {CREATE_NEW_WALLET_HELP_PAGE} from '../_shared/constants';
@Component({
selector: 'app-main',
@ -12,17 +13,23 @@ import {TranslateService} from '@ngx-translate/core';
})
export class MainComponent implements OnInit {
public prevUrl: string = '';
constructor(
private route: ActivatedRoute,
private router: Router,
private location: Location,
private backend: BackendService,
private variablesService: VariablesService,
public variablesService: VariablesService,
private ngZone: NgZone,
private translate: TranslateService
) {
}
ngOnInit() {
if (this.route.snapshot.queryParams && this.route.snapshot.queryParams.prevUrl) {
this.prevUrl = this.route.snapshot.queryParams.prevUrl;
}
}
openWallet() {
@ -39,7 +46,7 @@ export class MainComponent implements OnInit {
}
openInBrowser() {
this.backend.openUrlInBrowser('docs.zano.org/docs/getting-started-1#section-create-new-wallet');
this.backend.openUrlInBrowser(CREATE_NEW_WALLET_HELP_PAGE);
}
back() {

View file

@ -89,6 +89,7 @@ export class OpenWalletModalComponent implements OnInit {
new_wallet.is_auditable = open_data['wi'].is_auditable;
new_wallet.is_watch_only = open_data['wi'].is_watch_only;
new_wallet.currentPage = 1;
new_wallet.exclude_mining_txs = false;
if (open_data.recent_history && open_data.recent_history.history) {
new_wallet.total_history_item = open_data.recent_history.total_history_items;
new_wallet.totalPages = Math.ceil( open_data.recent_history.total_history_items / this.variablesService.count);
@ -124,10 +125,12 @@ export class OpenWalletModalComponent implements OnInit {
}
skipWallet() {
if (this.wallets.length) {
this.wallets.splice(0, 1);
this.ngOnInit();
}
this.ngZone.run(() => {
if (this.wallets.length) {
this.wallets.splice(0, 1);
this.ngOnInit();
}
});
}
}

View file

@ -33,7 +33,7 @@ export class OpenWalletComponent implements OnInit, OnDestroy {
private route: ActivatedRoute,
private router: Router,
private backend: BackendService,
private variablesService: VariablesService,
public variablesService: VariablesService,
private modalService: ModalService,
private ngZone: NgZone,
private translate: TranslateService
@ -98,6 +98,8 @@ export class OpenWalletComponent implements OnInit, OnDestroy {
);
new_wallet.alias = this.backend.getWalletAlias(new_wallet.address);
new_wallet.currentPage = 1;
new_wallet.open_from_exist = true;
new_wallet.exclude_mining_txs = false;
new_wallet.is_auditable = open_data['wi'].is_auditable;
new_wallet.is_watch_only = open_data['wi'].is_watch_only;
if (open_data.recent_history && open_data.recent_history.history) {

View file

@ -121,6 +121,8 @@ export class RestoreWalletComponent implements OnInit {
}
runWallet() {
// add flag when wallet was restored form seed
this.variablesService.after_sync_request[this.wallet.id] = true;
let exists = false;
this.variablesService.wallets.forEach((wallet) => {
if (wallet.address === this.variablesService.opening_wallet.address) {

View file

@ -2,30 +2,48 @@
<div class="title">
<span>{{ 'CONFIRM.TITLE' | translate }}</span>
</div>
<div class="content">
<div class="message-container">
<div class="message-block">
<div class="message-label">{{ 'CONFIRM.MESSAGE.SEND' | translate }}</div>
<div class="message-text">{{ +form.get('amount').value }} {{variablesService.defaultCurrency}}</div>
</div>
<div class="message-block">
<div class="message-label">{{ 'CONFIRM.MESSAGE.FROM' | translate }}</div>
<div class="message-text">{{ variablesService.currentWallet.address }}</div>
</div>
<div class="message-block">
<div class="message-label">{{ 'CONFIRM.MESSAGE.TO' | translate }}</div>
<div class="message-text">{{ form.get('address').value }}</div>
</div>
<ng-container *ngIf="form.get('comment').value != ''">
<div class="message-block" *ngIf="form.get('comment').value != null">
<div class="message-label">{{ 'CONFIRM.MESSAGE.COMMENT' | translate }}</div>
<div class="message-text">{{ form.get('comment').value }}</div>
<form [formGroup]="confirmForm" (ngSubmit)="confirm()">
<div class="content">
<div class="message-container">
<div class="message-block">
<div class="message-label">{{ 'CONFIRM.MESSAGE.SEND' | translate }}</div>
<div class="message-text">{{ +form.get('amount').value }} {{variablesService.defaultCurrency}}</div>
</div>
</ng-container>
<div class="message-block">
<div class="message-label">{{ 'CONFIRM.MESSAGE.FROM' | translate }}</div>
<div class="message-text">{{ variablesService.currentWallet.address }}</div>
</div>
<div class="message-block">
<div class="message-label">{{ 'CONFIRM.MESSAGE.TO' | translate }}</div>
<div class="message-text">{{ form.get('address').value }}</div>
</div>
<ng-container *ngIf="form.get('comment').value != ''">
<div class="message-block" *ngIf="form.get('comment').value != null">
<div class="message-label">{{ 'CONFIRM.MESSAGE.COMMENT' | translate }}</div>
<div class="message-text">{{ form.get('comment').value }}</div>
</div>
</ng-container>
<div class="message-block confirm-master-pass">
<div class="input-block" *ngIf="variablesService.appPass">
<label for="password">{{ 'LOGIN.MASTER_PASS' | translate }}</label>
<input type="password" id="password" name="password" formControlName="password" autofocus (contextmenu)="variablesService.onContextMenuPasteSelect($event)"/>
<div class="error-block" >
<div *ngIf="(confirmForm.controls['password'].errors && confirmForm.controls['password'].errors.requiredPass)
|| (!confirmForm.controls['password'].value && confirmForm.controls['password'].touched)">
{{ 'LOGIN.FORM_ERRORS.PASS_REQUIRED' | translate }}
</div>
<div *ngIf="confirmForm.controls['password'].errors && confirmForm.controls['password'].errors.passwordNotMatch">
{{ 'LOGIN.FORM_ERRORS.MISMATCH' | translate }}
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="wrapper-buttons">
<button type="button" class="blue-button" (click)="confirm()">{{ 'CONFIRM.BUTTON_CONFIRM' | translate }}</button>
<button type="button" class="blue-button" (click)="onClose()">{{ 'CONFIRM.BUTTON_CANCEL' | translate }}</button>
</div>
<div class="wrapper-buttons">
<button type="submit" class="blue-button" (click)="confirm()">{{ 'CONFIRM.BUTTON_CONFIRM' | translate }}</button>
<button type="button" class="blue-button" (click)="onClose()">{{ 'CONFIRM.BUTTON_CANCEL' | translate }}</button>
</div>
</form>
</div>

View file

@ -34,7 +34,7 @@
align-items: flex-start;
justify-content: center;
margin: 1.4rem 3rem 6.2rem 0;
.message-block {
display: flex;
margin-bottom: 1rem;
@ -65,8 +65,15 @@
width: 43.4rem;
line-height: 2rem;
}
}
&.confirm-master-pass {
width: 100%;
margin: 2rem 0;
.input-block {
width: 100%;
}
}
}
}
}

View file

@ -1,5 +1,5 @@
import { Component, OnInit, Output, EventEmitter, Input } from '@angular/core';
import { FormGroup } from '@angular/forms';
import { Component, OnInit, Output, EventEmitter, Input} from '@angular/core';
import {FormControl, FormGroup, Validators} from '@angular/forms';
import { VariablesService } from '../_helpers/services/variables.service';
@ -10,19 +10,40 @@ import { VariablesService } from '../_helpers/services/variables.service';
})
export class SendModalComponent implements OnInit {
confirmForm = new FormGroup({
password: new FormControl('')
});
@Input() form: FormGroup;
@Output() confirmed: EventEmitter<boolean> = new EventEmitter<boolean>();
constructor(
public variablesService: VariablesService
public variablesService: VariablesService,
) {
}
ngOnInit() {
if(this.variablesService.appPass) {
this.confirmForm.controls['password'].setValidators([Validators.required]);
this.confirmForm.updateValueAndValidity();
}
}
confirm() {
this.confirmed.emit(true);
if(this.variablesService.appPass) {
if (this.confirmForm.controls['password'].value === '') {
this.confirmForm.controls['password'].setErrors({requiredPass: true});
return;
}
this.confirmForm.controls['password'].setErrors({requiredPass: false});
if (this.variablesService.appPass === this.confirmForm.controls['password'].value) {
this.confirmed.emit(true);
} else {
this.confirmForm.controls['password'].setErrors({passwordNotMatch: true})
}
} else {
this.confirmed.emit(true);
}
}
onClose() {

View file

@ -4,11 +4,13 @@ import {BackendService} from '../_helpers/services/backend.service';
import {FormControl, FormGroup, Validators} from '@angular/forms';
import {Location} from '@angular/common';
import { TranslateService } from '@ngx-translate/core';
import {UtilsService} from '../_helpers/services/utils.service';
@Component({
selector: 'app-settings',
templateUrl: './settings.component.html',
styleUrls: ['./settings.component.scss']
styleUrls: ['./settings.component.scss'],
providers: [UtilsService]
})
export class SettingsComponent implements OnInit {
@ -103,7 +105,8 @@ export class SettingsComponent implements OnInit {
private backend: BackendService,
private location: Location,
public translate: TranslateService,
private ngZone: NgZone
private ngZone: NgZone,
private utilsService: UtilsService
) {
this.theme = this.variablesService.settings.theme;
this.scale = this.variablesService.settings.scale;
@ -122,9 +125,16 @@ export class SettingsComponent implements OnInit {
}
ngOnInit() {
this.backend.getVersion((version) => {
this.backend.getVersion((version, type) => {
this.ngZone.run(() => {
this.currentBuild = version;
this.variablesService.testnet = false;
if (type == 'testnet')
{
this.currentBuild += ' TESTNET';
this.variablesService.testnet = true;
}
this.variablesService.networkType = type;
});
});
}
@ -140,6 +150,9 @@ export class SettingsComponent implements OnInit {
setScale(scale) {
this.scale = scale;
this.variablesService.settings.scale = this.scale;
const width = this.utilsService.getMinWidthByScale(this.scale);
const app = document.documentElement.querySelector('app-root');
this.renderer.setStyle(app, 'min-width', width + 'px');
this.renderer.setStyle(document.documentElement, 'font-size', this.scale + 'px');
this.backend.storeAppData();
}

View file

@ -1,9 +1,9 @@
<div class="sidebar-accounts">
<div class="sidebar-accounts-header">
<h3>{{ 'SIDEBAR.TITLE' | translate }}</h3><button [routerLink]="['main']">{{ 'SIDEBAR.ADD_NEW' | translate }}</button>
<h3>{{ 'SIDEBAR.TITLE' | translate }}</h3><button (click)="goMainPage()">{{ 'SIDEBAR.ADD_NEW' | translate }}</button>
</div>
<div class="sidebar-accounts-list scrolled-content">
<div class="sidebar-account" *ngFor="let wallet of variablesService.wallets" [class.active]="wallet?.wallet_id === walletActive" [routerLink]="['/wallet/' + wallet.wallet_id + '/history']">
<div class="sidebar-account" *ngFor="let wallet of variablesService.wallets" [class.active]="wallet?.wallet_id === walletActive" [routerLink]="['/wallet/' + wallet.wallet_id + '/history']" [queryParams]="{sidenav: true}">
<div class="wallet-type" (click)="goToAuditableWalletHelpPage($event)">
<div class="content auditable" *ngIf="wallet.is_auditable && !wallet.is_watch_only">
Auditable
@ -12,7 +12,7 @@
Watch-only
</div>
<div class="content auditable-watch-only" *ngIf="wallet.is_auditable && wallet.is_watch_only">
Tracking
Tracking
</div>
</div>
<div class="close-wallet-wrapper">
@ -28,7 +28,7 @@
<div class="name">
<span tooltip="{{wallet.alias['name']}}" placement="top-left" tooltipClass="table-tooltip account-tooltip" [delay]="500" [showWhenNoOverflow]="false">{{wallet.alias['name']}}</span>
<ng-container *ngIf="wallet.alias['comment'] && wallet.alias['comment'].length">
<i class="icon comment" tooltip="{{wallet.alias['comment']}}" placement="top" tooltipClass="table-tooltip account-tooltip" [delay]="500"></i>
<span class="icon comment" tooltip="{{wallet.alias['comment']}}" placement="top" tooltipClass="table-tooltip account-tooltip" [delay]="500">i</span>
</ng-container>
</div>
<span class="price">$ {{wallet.getMoneyEquivalent(variablesService.moneyEquivalent) | intToMoney | number : '1.2-2'}}</span>
@ -111,7 +111,7 @@
</div>
</ng-template>
</div>
<div class="sidebar-synchronization-status" [ngStyle]="{'align-items': variablesService.daemon_state === 1 || variablesService.daemon_state === 6 ? 'flex-start' : 'center'}">
<div class="synchronization-status" [ngStyle]="{'align-items': variablesService.daemon_state === 1 || variablesService.daemon_state === 6 ? 'flex-start' : 'center'}">
<div class="status-container">
<span class="offline" *ngIf="variablesService.daemon_state === 0">
{{ 'SIDEBAR.SYNCHRONIZATION.OFFLINE' | translate }}

View file

@ -85,7 +85,7 @@
flex-direction: column;
flex: 1 1 auto;
margin: 0 -3rem;
overflow-y: overlay;
overflow-y: auto;
.sidebar-account {
position: relative;
@ -112,15 +112,20 @@
.icon {
width: 1.3rem;
height: 1.3rem;
&.close-wallet {
mask: url(../../assets/icons/close-wallet.svg) no-repeat center;
background-color: transparent;
}
&.close-wallet::after {
display: block;
content:'';
background:url("../../assets/icons/close-wallet-blue.svg") no-repeat center;
width: 13px;
height: 13px;
}
}
}
}
.sidebar-account-row {
display: flex;
align-items: center;
@ -169,12 +174,17 @@
.icon {
margin-left: 0.5rem;
width: 1.2rem;
height: 1.2rem;
&.comment {
mask: url(../../assets/icons/alert.svg) no-repeat center;
}
width: 1.3rem;
height: 1.3rem;
border-radius: 50%;
color: #1a1a1a;
font-size: 9px;
font-weight: 700;
line-height: 9px;
padding-right: 1px;
display: flex;
align-items: center;
justify-content: center;
}
}
@ -300,7 +310,7 @@
}
}
.sidebar-synchronization-status {
.synchronization-status {
display: flex;
align-items: center;
justify-content: flex-start;

View file

@ -4,6 +4,7 @@ import {VariablesService} from '../_helpers/services/variables.service';
import {BackendService} from '../_helpers/services/backend.service';
import { ModalService } from '../_helpers/services/modal.service';
import {AUDITABLE_WALLET_HELP_PAGE} from '../_shared/constants';
import {DOWNLOADS_PAGE_URL} from '../_shared/constants';
import icons from '../../assets/icons/icons.json';
@ -24,6 +25,8 @@ export class SidebarComponent implements OnInit, OnDestroy {
isModalDialogVisible = false;
closeWalletId: number;
menuItemHovered: boolean;
constructor(
private route: ActivatedRoute,
private router: Router,
@ -61,6 +64,19 @@ export class SidebarComponent implements OnInit, OnDestroy {
});
}
goMainPage() {
if (this.route.snapshot.queryParams && this.route.snapshot.queryParams.prevUrl === 'login') {
this.ngZone.run(() => {
this.router.navigate(['/'], {queryParams: {prevUrl: 'login'}});
});
} else {
this.ngZone.run(() => {
this.router.navigate(['/']);
});
}
};
contactsRoute() {
if (this.variablesService.appPass) {
this.router.navigate(['/contacts']);
@ -106,7 +122,7 @@ export class SidebarComponent implements OnInit, OnDestroy {
}
getUpdate() {
this.backend.openUrlInBrowser('zano.org/downloads.html');
this.backend.openUrlInBrowser(DOWNLOADS_PAGE_URL);
}
goToAuditableWalletHelpPage(e) {
e.preventDefault();

View file

@ -91,7 +91,7 @@ export class StakingComponent implements OnInit, OnDestroy {
constructor(
private route: ActivatedRoute,
private variablesService: VariablesService,
public variablesService: VariablesService,
private backend: BackendService,
private ngZone: NgZone,
private intToMoneyPipe: IntToMoneyPipe,

View file

@ -26,7 +26,7 @@ export class TransferAliasComponent implements OnInit {
private location: Location,
private router: Router,
private backend: BackendService,
private variablesService: VariablesService,
public variablesService: VariablesService,
private modalService: ModalService,
private ngZone: NgZone
) {}

View file

@ -32,7 +32,7 @@
<div class="tabs">
<div class="tabs-header">
<ng-container *ngFor="let tab of tabs; let index = index">
<div class="tab" [class.active]="tab.active"
<div class="tab" [class.active]="tab.active" [ngClass]="{ 'hide': ((tab.link === '/send' || tab.link === '/contracts') && variablesService.currentWallet.is_watch_only && variablesService.currentWallet.is_auditable) }"
[class.disabled]="((tab.link === '/send' || tab.link === '/contracts' || tab.link === '/staking') && (variablesService.daemon_state !== 2 || !variablesService.currentWallet.loaded))
|| ((tab.link === '/send' || tab.link === '/contracts') && variablesService.currentWallet.is_watch_only && variablesService.currentWallet.is_auditable)"
(click)="changeTab(index)" (mouseover)="itemHovered(index, true)" (mouseleave)="itemHovered(index, false)">
@ -50,12 +50,45 @@
</div>
<div *ngIf="activeTab === 'history'" class="pagination-wrapper">
<div class="pagination">
<button [disabled]="variablesService.currentWallet.currentPage === 1" (click)="setPage(variablesService.currentWallet.currentPage - 1)"><</button>
<ng-container *ngFor="let page of variablesService.currentWallet.pages">
<button [ngClass]="{ 'active': variablesService.currentWallet.currentPage === page }"
(click)="setPage(page)">{{page}}</button>
<div>
<button
[ngClass]="{'disabled': sync_started || wallet}"
[disabled]="variablesService.currentWallet.currentPage === 1 || sync_started || wallet"
(click)="setPage(variablesService.currentWallet.currentPage - 1)">
<
</button>
<ng-container *ngIf="!mining">
<button [disabled]="sync_started || wallet"
*ngFor="let page of variablesService.currentWallet.pages"
[ngClass]="{ 'active': variablesService.currentWallet.currentPage === page,'disabled': sync_started || wallet }"
(click)="setPage(page)">{{page}}</button>
</ng-container>
<button [disabled]="variablesService.currentWallet.currentPage === variablesService.currentWallet.totalPages" (click)="setPage(variablesService.currentWallet.currentPage + 1)">></button>
<ng-container *ngIf="mining">
<button [ngClass]="{ 'active': variablesService.currentWallet.currentPage, 'disabled': sync_started || wallet}"
[disabled]="stop_paginate || sync_started || wallet"
(click)="setPage(variablesService.currentWallet.currentPage)">
{{variablesService.currentWallet.currentPage}}
</button>
</ng-container>
<button
[disabled]="stop_paginate || sync_started || wallet"
[ngClass]="{'disabled': sync_started || wallet}"
(click)="setPage(variablesService.currentWallet.currentPage + 1)">
>
</button>
</div>
<div class="mining-transaction-switch">
<span class="switch-text">Hide mining transactions</span>
<div class="switch" [ngClass]="{'disabled': sync_started || wallet}" (click)="toggleMiningTransactions(); $event.stopPropagation()">
<span class="option" *ngIf="mining">{{ 'STAKING.SWITCH.ON' | translate }}</span>
<span class="circle" [class.on]="mining" [class.off]="!mining"></span>
<span class="option" *ngIf="!mining">{{ 'STAKING.SWITCH.OFF' | translate }}</span>
</div>
</div>
</div>
</div>
</div>

View file

@ -160,19 +160,21 @@
cursor: pointer;
padding: 0 1rem;
height: 5rem;
&.hide {
display: none;
}
.animated {
display: flex;
justify-content: center;
align-items: center;
margin-right: 1.3rem;
}
.animated ::ng-deep svg {
width: 2rem;
height: 2rem;
path, circle, polygon {
fill: #4db1ff;
}
@ -239,17 +241,62 @@
overflow-y: overlay;
}
.pagination-wrapper {
.pagination {
padding: 1rem;
display: flex;
justify-content: space-between;
align-items: center;
button {
margin-right: 0.5rem;
padding: 0;
width: 2.5rem;
height: 2.5rem;
font-size: 1.2rem;
transition: all 0.3s;
}
.disabled {
background-color: #18202a;
color: #e0e0e0;
opacity: 0.3;
cursor: default;
transition: all 0.3s;
}
}
}
}
.mining-transaction-switch {
display: flex;
align-items: center;
.switch-text {
margin-right: 1rem;
font-size: 1.3rem;
color: #565c62;
}
.switch {
display: flex;
align-items: center;
justify-content: space-between;
border-radius: 1rem;
cursor: pointer;
font-size: 1rem;
padding: 0.5rem;
width: 5rem;
height: 2rem;
.circle {
border-radius: 1rem;
width: 1.2rem;
height: 1.2rem;
}
.option {
margin: 0 0.2rem;
line-height: 1.2rem;
}
}
}

View file

@ -4,15 +4,20 @@ import { VariablesService } from '../_helpers/services/variables.service';
import { BackendService } from '../_helpers/services/backend.service';
import { TranslateService } from '@ngx-translate/core';
import { IntToMoneyPipe } from '../_helpers/pipes/int-to-money.pipe';
import { Subscription } from 'rxjs';
import {Subscription} from 'rxjs';
import { LOCKED_BALANCE_HELP_PAGE } from '../_shared/constants';
import icons from '../../assets/icons/icons.json';
import { PaginationService } from '../_helpers/services/pagination.service';
import {PaginationService} from '../_helpers/services/pagination.service';
import {PaginationStore} from '../_helpers/services/pagination.store';
import {Store, Sync} from 'store';
import {Wallet} from '../_helpers/models/wallet.model';
import {distinctUntilChanged, filter} from 'rxjs/operators';
@Component({
selector: 'app-wallet',
templateUrl: './wallet.component.html',
styleUrls: ['./wallet.component.scss']
styleUrls: ['./wallet.component.scss'],
})
export class WalletComponent implements OnInit, OnDestroy {
subRouting1;
@ -23,8 +28,11 @@ export class WalletComponent implements OnInit, OnDestroy {
copyAnimationTimeout;
balanceTooltip;
activeTab = 'history';
public mining = false;
public currentPage = 1;
wallet: Wallet;
sync_started = false;
stop_paginate = false;
@ViewChild('scrolledContent') private scrolledContent: ElementRef;
@ -85,6 +93,7 @@ export class WalletComponent implements OnInit, OnDestroy {
}
];
aliasSubscription: Subscription;
walletsSubscription: Subscription;
constructor(
private route: ActivatedRoute,
@ -94,20 +103,82 @@ export class WalletComponent implements OnInit, OnDestroy {
private ngZone: NgZone,
private translate: TranslateService,
private intToMoneyPipe: IntToMoneyPipe,
private pagination: PaginationService
private pagination: PaginationService,
private paginationStore: PaginationStore,
private store: Store,
) { }
ngOnInit() {
this.subRouting1 = this.route.params.subscribe(params => {
// set current wallet only by user click to avoid after sync show synchronized data
this.walletID = +params['id'];
this.variablesService.setCurrentWallet(this.walletID);
this.walletsSubscription = this.store.select('sync').pipe(
filter(Boolean),
distinctUntilChanged(),
).subscribe(value => {
const data = value.filter((item: Sync) => item.wallet_id === this.walletID)[0];
if (data && !data.sync) {
let in_progress;
const values = this.store.value.sync;
if (values && values.length) {
in_progress = values.filter(item => item.sync);
this.variablesService.sync_started = !!(in_progress && in_progress.length);
if (!in_progress) {
this.variablesService.sync_started = false;
}
} else {
this.variablesService.sync_started = false;
}
}
let restore = false;
if (this.variablesService.after_sync_request.hasOwnProperty(this.walletID)) {
restore = this.variablesService.after_sync_request[this.walletID];
}
if (!this.variablesService.sync_started && restore && this.walletID === (data && data.wallet_id)) {
this.wallet = this.variablesService.getNotLoadedWallet();
if (this.wallet) {
this.tick();
}
// if this is was restore wallet and it was selected on moment when sync completed
this.getRecentTransfers();
this.variablesService.after_sync_request[this.walletID] = false;
}
});
let after_sync_request = false;
if (this.variablesService.after_sync_request.hasOwnProperty(this.walletID)) {
after_sync_request = this.variablesService.after_sync_request[this.walletID];
}
if (after_sync_request && !this.variablesService.sync_started) {
// if user click on the wallet at the first time after restore.
this.getRecentTransfers();
}
if (this.variablesService.stop_paginate.hasOwnProperty(this.walletID)) {
this.stop_paginate = this.variablesService.stop_paginate[this.walletID];
} else {
this.stop_paginate = false;
}
// this will hide pagination a bit earlier
this.wallet = this.variablesService.getNotLoadedWallet();
if (this.wallet) {
this.tick();
}
this.scrolledContent.nativeElement.scrollTop = 0;
clearTimeout(this.copyAnimationTimeout);
this.copyAnimation = false;
this.mining = this.variablesService.currentWallet.exclude_mining_txs;
if (this.variablesService.wallets.length === 1) {
this.walletID = +params['id'];
this.variablesService.setCurrentWallet(this.walletID);
}
});
this.subRouting2 = this.router.events.subscribe(val => {
if (val instanceof RoutesRecognized) {
this.activeTab = val.urlAfterRedirects.split('/').pop();
this.activeTab = val.urlAfterRedirects.replace('?sidenav=true', '').split('/').pop();
if (val.state.root.firstChild && val.state.root.firstChild.firstChild) {
for (let i = 0; i < this.tabs.length; i++) {
this.tabs[i].active = (this.tabs[i].link === '/' + val.state.root.firstChild.firstChild.url[0].path);
@ -133,10 +204,26 @@ export class WalletComponent implements OnInit, OnDestroy {
}
});
}
resetPaginationValues() {
this.ngZone.run(() => {
const total_history_item = this.variablesService.currentWallet.total_history_item;
const count = this.variablesService.count;
this.variablesService.currentWallet.totalPages = Math.ceil( total_history_item / count);
this.variablesService.currentWallet.exclude_mining_txs = this.mining;
this.variablesService.currentWallet.currentPage = 1;
if (!this.variablesService.currentWallet.totalPages) {
this.variablesService.currentWallet.totalPages = 1;
}
this.variablesService.currentWallet.totalPages > this.variablesService.maxPages
? this.variablesService.currentWallet.pages = new Array(5).fill(1).map((value, index) => value + index)
: this.variablesService.currentWallet.pages = new Array(this.variablesService.currentWallet.totalPages).fill(1).map((value, index) => value + index);
})
}
changeTab(index) {
if (((this.tabs[index].link === '/send' || this.tabs[index].link === '/contracts' || this.tabs[index].link === '/staking') && (this.variablesService.daemon_state !== 2 || !this.variablesService.currentWallet.loaded))
|| ((this.tabs[index].link === '/send' || this.tabs[index].link === '/contracts') && this.variablesService.currentWallet.is_watch_only && this.variablesService.currentWallet.is_auditable)) {
|| ((this.tabs[index].link === '/send' || this.tabs[index].link === '/contracts') && this.variablesService.currentWallet.is_watch_only && this.variablesService.currentWallet.is_auditable)) {
return;
}
this.tabs.forEach((tab) => {
@ -175,7 +262,7 @@ export class WalletComponent implements OnInit, OnDestroy {
link.setAttribute('class', 'link');
link.innerHTML = this.translate.instant('WALLET.LOCKED_BALANCE_LINK');
link.addEventListener('click', () => {
this.openInBrowser('docs.zano.org/docs/locked-balance');
this.openInBrowser(LOCKED_BALANCE_HELP_PAGE);
});
this.balanceTooltip.appendChild(link);
return this.balanceTooltip;
@ -190,28 +277,84 @@ export class WalletComponent implements OnInit, OnDestroy {
}
public setPage(pageNumber: number) {
// this is will allow pagination for wallets that was open from existed wallets'
if (this.variablesService.currentWallet.open_from_exist && !this.variablesService.currentWallet.updated) {
this.variablesService.get_recent_transfers = false;
this.variablesService.currentWallet.updated = true;
}
if (pageNumber === this.variablesService.currentWallet.currentPage) {
return;
}
this.variablesService.currentWallet.currentPage = pageNumber;
// if not running get_recent_transfers callback
if (!this.variablesService.get_recent_transfers) {
this.variablesService.currentWallet.currentPage = pageNumber;
}
if (!this.variablesService.get_recent_transfers) {
this.getRecentTransfers();
}
}
toggleMiningTransactions() {
if (!this.variablesService.sync_started && !this.wallet) {
const value = this.paginationStore.value;
if (!value) {
this.paginationStore.setPage(1, 0, this.walletID); // add back page for the first page
} else {
const pages = value.filter(item => item.walletID === this.walletID);
if (!pages.length) {
this.paginationStore.setPage(1, 0, this.walletID); // add back page for the first page
}
}
this.mining = !this.mining;
this.resetPaginationValues();
this.getRecentTransfers();
}
}
tick() {
const walletInterval = setInterval(() => {
this.wallet = this.variablesService.getNotLoadedWallet();
if (!this.wallet) {
clearInterval(walletInterval);
}
}, 1000);
}
getRecentTransfers () {
const offset = this.pagination.getOffset(this.walletID);
const value = this.paginationStore.value;
const pages = value ? value.filter(item => item.walletID === this.walletID) : [];
this.backend.getRecentTransfers(
this.walletID,
(this.variablesService.currentWallet.currentPage - 1) * this.variablesService.count,
this.variablesService.count, (status, data) => {
if (status && data.total_history_items) {
this.variablesService.currentWallet.history.splice(0, this.variablesService.currentWallet.history.length);
this.ngZone.run(() => {
this.pagination.paginate(this.variablesService.currentWallet.currentPage);
if (data.history.length !== 0) {
this.variablesService.currentWallet.restore = false;
this.variablesService.currentWallet.total_history_item = data.total_history_items;
this.variablesService.currentWallet.prepareHistory(data.history);
if (this.variablesService.currentWallet.currentPage === 1 && data.unconfirmed) {
this.variablesService.currentWallet.prepareHistory(data.unconfirmed);
}
}
});
offset,
this.variablesService.count, this.variablesService.currentWallet.exclude_mining_txs, (status, data) => {
const isForward = this.paginationStore.isForward(pages, this.variablesService.currentWallet.currentPage);
if (this.mining && isForward && pages && pages.length === 1) {
this.variablesService.currentWallet.currentPage = 1; // set init page after navigation back
}
const history = (data && data.history);
this.variablesService.stop_paginate[this.walletID] = history && history.length < this.variablesService.count || !history;
this.stop_paginate = this.variablesService.stop_paginate[this.walletID];
if (!this.variablesService.stop_paginate[this.walletID]) {
const page = this.variablesService.currentWallet.currentPage + 1;
if (isForward && this.mining && history && history.length === this.variablesService.count) {
this.paginationStore.setPage(page, data.last_item_index, this.walletID); // add back page for current page
}
}
this.pagination.calcPages(data);
this.pagination.prepareHistory(data, status);
this.ngZone.run(() => {
this.variablesService.get_recent_transfers = false;
if (this.variablesService.after_sync_request.hasOwnProperty(this.walletID)) {
// this is will complete get_recent_transfers request
// this will switch of
this.variablesService.after_sync_request[this.walletID] = false;
}
});
});
}
@ -220,6 +363,9 @@ export class WalletComponent implements OnInit, OnDestroy {
this.subRouting2.unsubscribe();
this.queryRouting.unsubscribe();
this.aliasSubscription.unsubscribe();
if (this.walletsSubscription) {
this.walletsSubscription.unsubscribe();
}
clearTimeout(this.copyAnimationTimeout);
}

View file

@ -147,6 +147,12 @@
"TIME3": "1 hour",
"TIME4": "Never"
},
"SCALE": {
"75": "75% scale",
"100": "100% scale",
"125": "125% scale",
"150": "150% scale"
},
"MASTER_PASSWORD": {
"TITLE": "Update master password",
"OLD": "Old password",
@ -194,7 +200,7 @@
"ASSIGN_ALIAS": {
"NAME": {
"LABEL": "Alias",
"PLACEHOLDER": "@ Enter alias",
"PLACEHOLDER": " Enter alias",
"TOOLTIP": "An alias is a shortened form or your account. An alias can only include Latin letters, numbers and characters “.” and “-”. It must start with “@”."
},
"COMMENT": {
@ -206,7 +212,7 @@
"BUTTON_ASSIGN": "Assign",
"FORM_ERRORS": {
"NAME_REQUIRED": "Name is required",
"NAME_WRONG": "Alias has wrong name",
"NAME_WRONG": "Invalid name: allowed symbols \"0-9\", \"a-z\", \"-\", \".\"",
"NAME_LENGTH": "The alias must be 6-25 characters long",
"NAME_EXISTS": "Alias name already exists",
"NO_MONEY": "You do not have enough funds to assign this alias",

View file

@ -147,6 +147,12 @@
"TIME3": "1 hour",
"TIME4": "Never"
},
"SCALE": {
"75": "75% scale",
"100": "100% scale",
"125": "125% scale",
"150": "150% scale"
},
"MASTER_PASSWORD": {
"TITLE": "Update master password",
"OLD": "Old password",
@ -194,7 +200,7 @@
"ASSIGN_ALIAS": {
"NAME": {
"LABEL": "Alias",
"PLACEHOLDER": "@ Enter alias",
"PLACEHOLDER": " Enter alias",
"TOOLTIP": "An alias is a shortened form or your account. An alias can only include Latin letters, numbers and characters “.” and “-”. It must start with “@”."
},
"COMMENT": {
@ -206,7 +212,7 @@
"BUTTON_ASSIGN": "Assign",
"FORM_ERRORS": {
"NAME_REQUIRED": "Name is required",
"NAME_WRONG": "Alias has wrong name",
"NAME_WRONG": "Invalid name: allowed symbols \"0-9\", \"a-z\", \"-\", \".\"",
"NAME_LENGTH": "The alias must be 6-25 characters long",
"NAME_EXISTS": "Alias name already exists",
"NO_MONEY": "You do not have enough funds to assign this alias",

View file

@ -147,6 +147,12 @@
"TIME3": "1 hour",
"TIME4": "Never"
},
"SCALE": {
"75": "75% scale",
"100": "100% scale",
"125": "125% scale",
"150": "150% scale"
},
"MASTER_PASSWORD": {
"TITLE": "Update master password",
"OLD": "Old password",
@ -194,7 +200,7 @@
"ASSIGN_ALIAS": {
"NAME": {
"LABEL": "Alias",
"PLACEHOLDER": "@ Enter alias",
"PLACEHOLDER": " Enter alias",
"TOOLTIP": "An alias is a shortened form or your account. An alias can only include Latin letters, numbers and characters “.” and “-”. It must start with “@”."
},
"COMMENT": {
@ -206,7 +212,7 @@
"BUTTON_ASSIGN": "Assign",
"FORM_ERRORS": {
"NAME_REQUIRED": "Name is required",
"NAME_WRONG": "Alias has wrong name",
"NAME_WRONG": "Invalid name: allowed symbols \"0-9\", \"a-z\", \"-\", \".\"",
"NAME_LENGTH": "The alias must be 6-25 characters long",
"NAME_EXISTS": "Alias name already exists",
"NO_MONEY": "You do not have enough funds to assign this alias",

View file

@ -147,6 +147,12 @@
"TIME3": "1 hour",
"TIME4": "Never"
},
"SCALE": {
"75": "75% scale",
"100": "100% scale",
"125": "125% scale",
"150": "150% scale"
},
"MASTER_PASSWORD": {
"TITLE": "Update master password",
"OLD": "Old password",
@ -194,7 +200,7 @@
"ASSIGN_ALIAS": {
"NAME": {
"LABEL": "Alias",
"PLACEHOLDER": "@ Enter alias",
"PLACEHOLDER": " Enter alias",
"TOOLTIP": "An alias is a shortened form or your account. An alias can only include Latin letters, numbers and characters “.” and “-”. It must start with “@”."
},
"COMMENT": {
@ -206,7 +212,7 @@
"BUTTON_ASSIGN": "Assign",
"FORM_ERRORS": {
"NAME_REQUIRED": "Name is required",
"NAME_WRONG": "Alias has wrong name",
"NAME_WRONG": "Invalid name: allowed symbols \"0-9\", \"a-z\", \"-\", \".\"",
"NAME_LENGTH": "The alias must be 6-25 characters long",
"NAME_EXISTS": "Alias name already exists",
"NO_MONEY": "You do not have enough funds to assign this alias",

View file

@ -147,6 +147,12 @@
"TIME3": "1 hour",
"TIME4": "Never"
},
"SCALE": {
"75": "75% scale",
"100": "100% scale",
"125": "125% scale",
"150": "150% scale"
},
"MASTER_PASSWORD": {
"TITLE": "Update master password",
"OLD": "Old password",
@ -194,7 +200,7 @@
"ASSIGN_ALIAS": {
"NAME": {
"LABEL": "Alias",
"PLACEHOLDER": "@ Enter alias",
"PLACEHOLDER": " Enter alias",
"TOOLTIP": "An alias is a shortened form or your account. An alias can only include Latin letters, numbers and characters “.” and “-”. It must start with “@”."
},
"COMMENT": {
@ -206,7 +212,7 @@
"BUTTON_ASSIGN": "Assign",
"FORM_ERRORS": {
"NAME_REQUIRED": "Name is required",
"NAME_WRONG": "Alias has wrong name",
"NAME_WRONG": "Invalid name: allowed symbols \"0-9\", \"a-z\", \"-\", \".\"",
"NAME_LENGTH": "The alias must be 6-25 characters long",
"NAME_EXISTS": "Alias name already exists",
"NO_MONEY": "You do not have enough funds to assign this alias",

View file

@ -147,6 +147,12 @@
"TIME3": "1 Stunde",
"TIME4": "Nie"
},
"SCALE": {
"75": "75% Rahmen",
"100": "100% Rahmen",
"125": "125% Rahmen",
"150": "150% Rahmen"
},
"MASTER_PASSWORD": {
"TITLE": "Master-Passwort aktualisieren",
"OLD": "Altes Passwort",
@ -194,7 +200,7 @@
"ASSIGN_ALIAS": {
"NAME": {
"LABEL": "Alias",
"PLACEHOLDER": "@ Alias eingeben",
"PLACEHOLDER": " Alias eingeben",
"TOOLTIP": "Ein Alias ist eine verkürzte Form Ihres Kontos. Ein Alias kann nur lateinische Buchstaben, Zahlen und die Zeichen „.“ und “-” enthalten. Es muss mit “@” beginnen."
},
"COMMENT": {
@ -206,7 +212,7 @@
"BUTTON_ASSIGN": "Zuweisen",
"FORM_ERRORS": {
"NAME_REQUIRED": "Name ist erforderlich",
"NAME_WRONG": "Alias hat einen falschen Namen",
"NAME_WRONG": "Ungültiger Name: zulässige Symbole \"0-9\", \"a-z\", \"-\", \".\"",
"NAME_LENGTH": "Der Alias muss 6-25 Zeichen lang sein",
"NAME_EXISTS": "Alias-Name existiert bereits",
"NO_MONEY": "Du hast nicht genug Geldmittel, um diesen Alias zuzuweisen",

View file

@ -147,6 +147,12 @@
"TIME3": "1 hour",
"TIME4": "Never"
},
"SCALE": {
"75": "75% scale",
"100": "100% scale",
"125": "125% scale",
"150": "150% scale"
},
"MASTER_PASSWORD": {
"TITLE": "Update master password",
"OLD": "Old password",
@ -194,7 +200,7 @@
"ASSIGN_ALIAS": {
"NAME": {
"LABEL": "Alias",
"PLACEHOLDER": "@ Enter alias",
"PLACEHOLDER": " Enter alias",
"TOOLTIP": "An alias is a shortened form or your account. An alias can only include Latin letters, numbers and characters “.” and “-”. It must start with “@”."
},
"COMMENT": {

View file

@ -223,7 +223,7 @@
"ASSIGN_ALIAS": {
"NAME": {
"LABEL": "Alias",
"PLACEHOLDER": "@ Enter alias",
"PLACEHOLDER": " Enter alias",
"TOOLTIP": "An alias is a shortened form or your account. An alias can only include Latin letters, numbers and characters “.” and “-”. It must start with “@”."
},
"COMMENT": {
@ -235,7 +235,7 @@
"BUTTON_ASSIGN": "Assign",
"FORM_ERRORS": {
"NAME_REQUIRED": "Name is required",
"NAME_WRONG": "Alias has wrong name",
"NAME_WRONG": "Invalid name: allowed symbols \"0-9\", \"a-z\", \"-\", \".\"",
"NAME_LENGTH": "The alias must be 6-25 characters long",
"NAME_EXISTS": "Alias name already exists",
"NO_MONEY": "You do not have enough funds to assign this alias",

View file

@ -147,6 +147,12 @@
"TIME3": "1 hour",
"TIME4": "Never"
},
"SCALE": {
"75": "75% scale",
"100": "100% scale",
"125": "125% scale",
"150": "150% scale"
},
"MASTER_PASSWORD": {
"TITLE": "Update master password",
"OLD": "Old password",
@ -194,7 +200,7 @@
"ASSIGN_ALIAS": {
"NAME": {
"LABEL": "Alias",
"PLACEHOLDER": "@ Enter alias",
"PLACEHOLDER": " Enter alias",
"TOOLTIP": "An alias is a shortened form or your account. An alias can only include Latin letters, numbers and characters “.” and “-”. It must start with “@”."
},
"COMMENT": {
@ -206,7 +212,7 @@
"BUTTON_ASSIGN": "Assign",
"FORM_ERRORS": {
"NAME_REQUIRED": "Name is required",
"NAME_WRONG": "Alias has wrong name",
"NAME_WRONG": "Nombre no válido: símbolos permitidos \"0-9\", \"a-z\", \"-\", \".\"",
"NAME_LENGTH": "The alias must be 6-25 characters long",
"NAME_EXISTS": "Alias name already exists",
"NO_MONEY": "You do not have enough funds to assign this alias",

View file

@ -147,6 +147,12 @@
"TIME3": "1 hour",
"TIME4": "Never"
},
"SCALE": {
"75": "75% scale",
"100": "100% scale",
"125": "125% scale",
"150": "150% scale"
},
"MASTER_PASSWORD": {
"TITLE": "Update master password",
"OLD": "Old password",
@ -194,7 +200,7 @@
"ASSIGN_ALIAS": {
"NAME": {
"LABEL": "Alias",
"PLACEHOLDER": "@ Enter alias",
"PLACEHOLDER": " Enter alias",
"TOOLTIP": "An alias is a shortened form or your account. An alias can only include Latin letters, numbers and characters “.” and “-”. It must start with “@”."
},
"COMMENT": {
@ -206,7 +212,7 @@
"BUTTON_ASSIGN": "Assign",
"FORM_ERRORS": {
"NAME_REQUIRED": "Name is required",
"NAME_WRONG": "Alias has wrong name",
"NAME_WRONG": "Invalid name: allowed symbols \"0-9\", \"a-z\", \"-\", \".\"",
"NAME_LENGTH": "The alias must be 6-25 characters long",
"NAME_EXISTS": "Alias name already exists",
"NO_MONEY": "You do not have enough funds to assign this alias",

Some files were not shown because too many files have changed in this diff Show more