SHA256
Доделать связи и профиль
This commit is contained in:
@@ -102,16 +102,23 @@ public final class MsgSubType {
|
|||||||
/** Удалить из близких друзей (close friend). */
|
/** Удалить из близких друзей (close friend). */
|
||||||
public static final short CONNECTION_UNCLOSE_FRIEND = 11;
|
public static final short CONNECTION_UNCLOSE_FRIEND = 11;
|
||||||
|
|
||||||
|
/** Добавить в друзья. */
|
||||||
|
public static final short CONNECTION_FRIEND = 14;
|
||||||
|
/** Удалить из друзей. */
|
||||||
|
public static final short CONNECTION_UNFRIEND = 15;
|
||||||
|
|
||||||
/** Добавить в контакты. */
|
/** Добавить в контакты. */
|
||||||
public static final short CONNECTION_CONTACT = 20;
|
public static final short CONNECTION_CONTACT = 20;
|
||||||
/** Удалить из контактов. */
|
/** Удалить из контактов. */
|
||||||
public static final short CONNECTION_UNCONTACT = 21;
|
public static final short CONNECTION_UNCONTACT = 21;
|
||||||
|
|
||||||
|
// Пока не используется в UI. Сохраняем для совместимости протокола/блокчейна. DO NOT REMOVE.
|
||||||
/** Подписаться (follow). */
|
/** Подписаться (follow). */
|
||||||
public static final short CONNECTION_FOLLOW = 30;
|
public static final short CONNECTION_FOLLOW = 30;
|
||||||
/** Отписаться (unfollow). */
|
/** Отписаться (unfollow). */
|
||||||
public static final short CONNECTION_UNFOLLOW = 31;
|
public static final short CONNECTION_UNFOLLOW = 31;
|
||||||
|
|
||||||
|
// Родственные связи пока не используются в UI. Сохраняем коды. DO NOT REMOVE.
|
||||||
/** Добавить связь "жена/муж". */
|
/** Добавить связь "жена/муж". */
|
||||||
public static final short CONNECTION_SPOUSE = 40;
|
public static final short CONNECTION_SPOUSE = 40;
|
||||||
/** Удалить связь "жена/муж". */
|
/** Удалить связь "жена/муж". */
|
||||||
@@ -132,9 +139,8 @@ public final class MsgSubType {
|
|||||||
/** Удалить связь "брат/сестра". */
|
/** Удалить связь "брат/сестра". */
|
||||||
public static final short CONNECTION_UNSIBLING = 55;
|
public static final short CONNECTION_UNSIBLING = 55;
|
||||||
|
|
||||||
/** Просто знаю этого человека. */
|
// Legacy. Допускаем старые блоки 60/61, но новый UI их не создаёт и не использует. DO NOT REMOVE.
|
||||||
public static final short CONNECTION_KNOWN_PERSON = 60;
|
public static final short CONNECTION_KNOWN_PERSON = 60;
|
||||||
/** Не знаю этого человека. */
|
|
||||||
public static final short CONNECTION_UNKNOWN_PERSON = 61;
|
public static final short CONNECTION_UNKNOWN_PERSON = 61;
|
||||||
|
|
||||||
/** Точно уверен, что сияющий. */
|
/** Точно уверен, что сияющий. */
|
||||||
@@ -142,11 +148,17 @@ public final class MsgSubType {
|
|||||||
/** Не подтверждаю, что сияющий. */
|
/** Не подтверждаю, что сияющий. */
|
||||||
public static final short CONNECTION_SHINE_UNCONFIRMED = 71;
|
public static final short CONNECTION_SHINE_UNCONFIRMED = 71;
|
||||||
|
|
||||||
|
// Пока не используется в UI. Сохраняем для совместимости протокола/блокчейна. DO NOT REMOVE.
|
||||||
/** Мало знаком, но видел сияющим. */
|
/** Мало знаком, но видел сияющим. */
|
||||||
public static final short CONNECTION_SHINE_SEEN = 74;
|
public static final short CONNECTION_SHINE_SEEN = 74;
|
||||||
/** Не отмечаю, что видел сияющим. */
|
/** Не отмечаю, что видел сияющим. */
|
||||||
public static final short CONNECTION_SHINE_UNSEEN = 75;
|
public static final short CONNECTION_SHINE_UNSEEN = 75;
|
||||||
|
|
||||||
|
/** Подтверждаю, что это действительно официальный аккаунт этого человека. */
|
||||||
|
public static final short CONNECTION_OFFICIAL_ACCOUNT_CONFIRMED = 80;
|
||||||
|
/** Снимаю подтверждение официального аккаунта этого человека. */
|
||||||
|
public static final short CONNECTION_OFFICIAL_ACCOUNT_UNCONFIRMED = 81;
|
||||||
|
|
||||||
/* ===================== USER_PARAM (msg_type=4) ===================== */
|
/* ===================== USER_PARAM (msg_type=4) ===================== */
|
||||||
|
|
||||||
/** Параметр профиля key/value (обе строки). */
|
/** Параметр профиля key/value (обе строки). */
|
||||||
|
|||||||
+9
-3
@@ -20,9 +20,11 @@ import java.util.Objects;
|
|||||||
* PARENT=50, UNPARENT=51
|
* PARENT=50, UNPARENT=51
|
||||||
* CHILD=52, UNCHILD=53
|
* CHILD=52, UNCHILD=53
|
||||||
* SIBLING=54, UNSIBLING=55
|
* SIBLING=54, UNSIBLING=55
|
||||||
* KNOWN_PERSON=60, UNKNOWN_PERSON=61
|
* FRIEND=14, UNFRIEND=15
|
||||||
|
* KNOWN_PERSON=60, UNKNOWN_PERSON=61 (legacy; accepted but not used by current UI)
|
||||||
* SHINE_CONFIRMED=70, SHINE_UNCONFIRMED=71
|
* SHINE_CONFIRMED=70, SHINE_UNCONFIRMED=71
|
||||||
* SHINE_SEEN=74, SHINE_UNSEEN=75
|
* SHINE_SEEN=74, SHINE_UNSEEN=75 (currently not used by UI)
|
||||||
|
* OFFICIAL_ACCOUNT_CONFIRMED=80, OFFICIAL_ACCOUNT_UNCONFIRMED=81
|
||||||
*
|
*
|
||||||
* bodyBytes (BigEndian), новый формат (toLogin НЕ ХРАНИМ):
|
* bodyBytes (BigEndian), новый формат (toLogin НЕ ХРАНИМ):
|
||||||
* [4] lineCode
|
* [4] lineCode
|
||||||
@@ -185,6 +187,8 @@ public final class ConnectionBody implements BodyRecord, BodyHasTarget, BodyHasL
|
|||||||
int v = st & 0xFFFF;
|
int v = st & 0xFFFF;
|
||||||
return v == (MsgSubType.CONNECTION_CLOSE_FRIEND & 0xFFFF)
|
return v == (MsgSubType.CONNECTION_CLOSE_FRIEND & 0xFFFF)
|
||||||
|| v == (MsgSubType.CONNECTION_UNCLOSE_FRIEND & 0xFFFF)
|
|| v == (MsgSubType.CONNECTION_UNCLOSE_FRIEND & 0xFFFF)
|
||||||
|
|| v == (MsgSubType.CONNECTION_FRIEND & 0xFFFF)
|
||||||
|
|| v == (MsgSubType.CONNECTION_UNFRIEND & 0xFFFF)
|
||||||
|| v == (MsgSubType.CONNECTION_CONTACT & 0xFFFF)
|
|| v == (MsgSubType.CONNECTION_CONTACT & 0xFFFF)
|
||||||
|| v == (MsgSubType.CONNECTION_UNCONTACT & 0xFFFF)
|
|| v == (MsgSubType.CONNECTION_UNCONTACT & 0xFFFF)
|
||||||
|| v == (MsgSubType.CONNECTION_FOLLOW & 0xFFFF)
|
|| v == (MsgSubType.CONNECTION_FOLLOW & 0xFFFF)
|
||||||
@@ -202,7 +206,9 @@ public final class ConnectionBody implements BodyRecord, BodyHasTarget, BodyHasL
|
|||||||
|| v == (MsgSubType.CONNECTION_SHINE_CONFIRMED & 0xFFFF)
|
|| v == (MsgSubType.CONNECTION_SHINE_CONFIRMED & 0xFFFF)
|
||||||
|| v == (MsgSubType.CONNECTION_SHINE_UNCONFIRMED & 0xFFFF)
|
|| v == (MsgSubType.CONNECTION_SHINE_UNCONFIRMED & 0xFFFF)
|
||||||
|| v == (MsgSubType.CONNECTION_SHINE_SEEN & 0xFFFF)
|
|| v == (MsgSubType.CONNECTION_SHINE_SEEN & 0xFFFF)
|
||||||
|| v == (MsgSubType.CONNECTION_SHINE_UNSEEN & 0xFFFF);
|
|| v == (MsgSubType.CONNECTION_SHINE_UNSEEN & 0xFFFF)
|
||||||
|
|| v == (MsgSubType.CONNECTION_OFFICIAL_ACCOUNT_CONFIRMED & 0xFFFF)
|
||||||
|
|| v == (MsgSubType.CONNECTION_OFFICIAL_ACCOUNT_UNCONFIRMED & 0xFFFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ public final class DatabaseInitializer {
|
|||||||
public static final int SCHEMA_VERSION_14 = 14;
|
public static final int SCHEMA_VERSION_14 = 14;
|
||||||
public static final int SCHEMA_VERSION_15 = 15;
|
public static final int SCHEMA_VERSION_15 = 15;
|
||||||
public static final int SCHEMA_VERSION_16 = 16;
|
public static final int SCHEMA_VERSION_16 = 16;
|
||||||
|
public static final int SCHEMA_VERSION_17 = 17;
|
||||||
public static final String POSTGRES_SCHEMA_RESOURCE = "postgres/schema_v1.sql";
|
public static final String POSTGRES_SCHEMA_RESOURCE = "postgres/schema_v1.sql";
|
||||||
public static final String POSTGRES_MIGRATION_V2_RESOURCE = "postgres/migration_v2.sql";
|
public static final String POSTGRES_MIGRATION_V2_RESOURCE = "postgres/migration_v2.sql";
|
||||||
public static final String POSTGRES_MIGRATION_V3_RESOURCE = "postgres/migration_v3.sql";
|
public static final String POSTGRES_MIGRATION_V3_RESOURCE = "postgres/migration_v3.sql";
|
||||||
@@ -49,6 +50,7 @@ public final class DatabaseInitializer {
|
|||||||
public static final String POSTGRES_MIGRATION_V14_RESOURCE = "postgres/migration_v14.sql";
|
public static final String POSTGRES_MIGRATION_V14_RESOURCE = "postgres/migration_v14.sql";
|
||||||
public static final String POSTGRES_MIGRATION_V15_RESOURCE = "postgres/migration_v15.sql";
|
public static final String POSTGRES_MIGRATION_V15_RESOURCE = "postgres/migration_v15.sql";
|
||||||
public static final String POSTGRES_MIGRATION_V16_RESOURCE = "postgres/migration_v16.sql";
|
public static final String POSTGRES_MIGRATION_V16_RESOURCE = "postgres/migration_v16.sql";
|
||||||
|
public static final String POSTGRES_MIGRATION_V17_RESOURCE = "postgres/migration_v17.sql";
|
||||||
|
|
||||||
private DatabaseInitializer() {}
|
private DatabaseInitializer() {}
|
||||||
|
|
||||||
@@ -70,12 +72,17 @@ public final class DatabaseInitializer {
|
|||||||
public static final short CONNECTION_CLOSE_FRIEND = 10;
|
public static final short CONNECTION_CLOSE_FRIEND = 10;
|
||||||
public static final short CONNECTION_UNCLOSE_FRIEND = 11;
|
public static final short CONNECTION_UNCLOSE_FRIEND = 11;
|
||||||
|
|
||||||
|
public static final short CONNECTION_FRIEND = 14;
|
||||||
|
public static final short CONNECTION_UNFRIEND = 15;
|
||||||
|
|
||||||
public static final short CONNECTION_CONTACT = 20;
|
public static final short CONNECTION_CONTACT = 20;
|
||||||
public static final short CONNECTION_UNCONTACT = 21;
|
public static final short CONNECTION_UNCONTACT = 21;
|
||||||
|
|
||||||
|
// Пока не используется в UI. DO NOT REMOVE.
|
||||||
public static final short CONNECTION_FOLLOW = 30;
|
public static final short CONNECTION_FOLLOW = 30;
|
||||||
public static final short CONNECTION_UNFOLLOW = 31;
|
public static final short CONNECTION_UNFOLLOW = 31;
|
||||||
|
|
||||||
|
// Родственные связи пока не используются в UI. DO NOT REMOVE.
|
||||||
public static final short CONNECTION_SPOUSE = 40;
|
public static final short CONNECTION_SPOUSE = 40;
|
||||||
public static final short CONNECTION_UNSPOUSE = 41;
|
public static final short CONNECTION_UNSPOUSE = 41;
|
||||||
|
|
||||||
@@ -88,15 +95,20 @@ public final class DatabaseInitializer {
|
|||||||
public static final short CONNECTION_SIBLING = 54;
|
public static final short CONNECTION_SIBLING = 54;
|
||||||
public static final short CONNECTION_UNSIBLING = 55;
|
public static final short CONNECTION_UNSIBLING = 55;
|
||||||
|
|
||||||
|
// Legacy 60/61: новый UI не использует. DO NOT REMOVE.
|
||||||
public static final short CONNECTION_KNOWN_PERSON = 60;
|
public static final short CONNECTION_KNOWN_PERSON = 60;
|
||||||
public static final short CONNECTION_UNKNOWN_PERSON = 61;
|
public static final short CONNECTION_UNKNOWN_PERSON = 61;
|
||||||
|
|
||||||
public static final short CONNECTION_SHINE_CONFIRMED = 70;
|
public static final short CONNECTION_SHINE_CONFIRMED = 70;
|
||||||
public static final short CONNECTION_SHINE_UNCONFIRMED = 71;
|
public static final short CONNECTION_SHINE_UNCONFIRMED = 71;
|
||||||
|
|
||||||
|
// Пока не используется в UI. DO NOT REMOVE.
|
||||||
public static final short CONNECTION_SHINE_SEEN = 74;
|
public static final short CONNECTION_SHINE_SEEN = 74;
|
||||||
public static final short CONNECTION_SHINE_UNSEEN = 75;
|
public static final short CONNECTION_SHINE_UNSEEN = 75;
|
||||||
|
|
||||||
|
public static final short CONNECTION_OFFICIAL_ACCOUNT_CONFIRMED = 80;
|
||||||
|
public static final short CONNECTION_OFFICIAL_ACCOUNT_UNCONFIRMED = 81;
|
||||||
|
|
||||||
public static void ensurePostgresSchemaInitialized(String jdbcUrl,
|
public static void ensurePostgresSchemaInitialized(String jdbcUrl,
|
||||||
String user,
|
String user,
|
||||||
String password) throws SQLException {
|
String password) throws SQLException {
|
||||||
@@ -172,6 +184,10 @@ public final class DatabaseInitializer {
|
|||||||
runSqlScript(conn, POSTGRES_MIGRATION_V16_RESOURCE);
|
runSqlScript(conn, POSTGRES_MIGRATION_V16_RESOURCE);
|
||||||
currentVersion = SCHEMA_VERSION_16;
|
currentVersion = SCHEMA_VERSION_16;
|
||||||
}
|
}
|
||||||
|
if (currentVersion < SCHEMA_VERSION_17) {
|
||||||
|
runSqlScript(conn, POSTGRES_MIGRATION_V17_RESOURCE);
|
||||||
|
currentVersion = SCHEMA_VERSION_17;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -58,10 +58,10 @@ public final class MsgSubType {
|
|||||||
/* ===================== CONNECTION (msg_type=3) ===================== */
|
/* ===================== CONNECTION (msg_type=3) ===================== */
|
||||||
/**
|
/**
|
||||||
* Совпадает с ConnectionBody:
|
* Совпадает с ConnectionBody:
|
||||||
* SET: CLOSE_FRIEND=10, CONTACT=20, FOLLOW=30, SPOUSE=40, PARENT=50, CHILD=52, SIBLING=54,
|
* SET: CLOSE_FRIEND=10, FRIEND=14, CONTACT=20, FOLLOW=30, SPOUSE=40, PARENT=50, CHILD=52, SIBLING=54,
|
||||||
* KNOWN_PERSON=60, SHINE_CONFIRMED=70, SHINE_SEEN=74
|
* KNOWN_PERSON(legacy)=60, SHINE_CONFIRMED=70, SHINE_SEEN=74, OFFICIAL_ACCOUNT_CONFIRMED=80
|
||||||
* UNSET: UNCLOSE_FRIEND=11, UNCONTACT=21, UNFOLLOW=31, UNSPOUSE=41, UNPARENT=51, UNCHILD=53, UNSIBLING=55,
|
* UNSET: UNCLOSE_FRIEND=11, UNFRIEND=15, UNCONTACT=21, UNFOLLOW=31, UNSPOUSE=41, UNPARENT=51, UNCHILD=53, UNSIBLING=55,
|
||||||
* UNKNOWN_PERSON=61, SHINE_UNCONFIRMED=71, SHINE_UNSEEN=75
|
* UNKNOWN_PERSON(legacy)=61, SHINE_UNCONFIRMED=71, SHINE_UNSEEN=75, OFFICIAL_ACCOUNT_UNCONFIRMED=81
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** Добавить в близкие друзья (close friend). */
|
/** Добавить в близкие друзья (close friend). */
|
||||||
@@ -70,18 +70,26 @@ public final class MsgSubType {
|
|||||||
/** Удалить из близких друзей (close friend). */
|
/** Удалить из близких друзей (close friend). */
|
||||||
public static final short CONNECTION_UNCLOSE_FRIEND = 11;
|
public static final short CONNECTION_UNCLOSE_FRIEND = 11;
|
||||||
|
|
||||||
|
/** Добавить в друзья. */
|
||||||
|
public static final short CONNECTION_FRIEND = 14;
|
||||||
|
|
||||||
|
/** Удалить из друзей. */
|
||||||
|
public static final short CONNECTION_UNFRIEND = 15;
|
||||||
|
|
||||||
/** Добавить в контакты. */
|
/** Добавить в контакты. */
|
||||||
public static final short CONNECTION_CONTACT = 20;
|
public static final short CONNECTION_CONTACT = 20;
|
||||||
|
|
||||||
/** Удалить из контактов. */
|
/** Удалить из контактов. */
|
||||||
public static final short CONNECTION_UNCONTACT = 21;
|
public static final short CONNECTION_UNCONTACT = 21;
|
||||||
|
|
||||||
|
// Пока не используется в UI. Сохраняем для совместимости. DO NOT REMOVE.
|
||||||
/** Подписаться (follow). */
|
/** Подписаться (follow). */
|
||||||
public static final short CONNECTION_FOLLOW = 30;
|
public static final short CONNECTION_FOLLOW = 30;
|
||||||
|
|
||||||
/** Отписаться (unfollow). */
|
/** Отписаться (unfollow). */
|
||||||
public static final short CONNECTION_UNFOLLOW = 31;
|
public static final short CONNECTION_UNFOLLOW = 31;
|
||||||
|
|
||||||
|
// Родственные связи пока не используются в UI. Сохраняем коды. DO NOT REMOVE.
|
||||||
/** Добавить связь "жена/муж". */
|
/** Добавить связь "жена/муж". */
|
||||||
public static final short CONNECTION_SPOUSE = 40;
|
public static final short CONNECTION_SPOUSE = 40;
|
||||||
|
|
||||||
@@ -106,10 +114,8 @@ public final class MsgSubType {
|
|||||||
/** Удалить связь "брат/сестра". */
|
/** Удалить связь "брат/сестра". */
|
||||||
public static final short CONNECTION_UNSIBLING = 55;
|
public static final short CONNECTION_UNSIBLING = 55;
|
||||||
|
|
||||||
/** Просто знаю этого человека. */
|
// Legacy 60/61: принимаем старые данные, но новый UI их не использует. DO NOT REMOVE.
|
||||||
public static final short CONNECTION_KNOWN_PERSON = 60;
|
public static final short CONNECTION_KNOWN_PERSON = 60;
|
||||||
|
|
||||||
/** Не знаю этого человека. */
|
|
||||||
public static final short CONNECTION_UNKNOWN_PERSON = 61;
|
public static final short CONNECTION_UNKNOWN_PERSON = 61;
|
||||||
|
|
||||||
/** Точно уверен, что сияющий. */
|
/** Точно уверен, что сияющий. */
|
||||||
@@ -118,12 +124,19 @@ public final class MsgSubType {
|
|||||||
/** Не подтверждаю, что сияющий. */
|
/** Не подтверждаю, что сияющий. */
|
||||||
public static final short CONNECTION_SHINE_UNCONFIRMED = 71;
|
public static final short CONNECTION_SHINE_UNCONFIRMED = 71;
|
||||||
|
|
||||||
|
// Пока не используется в UI. Сохраняем для совместимости. DO NOT REMOVE.
|
||||||
/** Мало знаком, но видел сияющим. */
|
/** Мало знаком, но видел сияющим. */
|
||||||
public static final short CONNECTION_SHINE_SEEN = 74;
|
public static final short CONNECTION_SHINE_SEEN = 74;
|
||||||
|
|
||||||
/** Не отмечаю, что видел сияющим. */
|
/** Не отмечаю, что видел сияющим. */
|
||||||
public static final short CONNECTION_SHINE_UNSEEN = 75;
|
public static final short CONNECTION_SHINE_UNSEEN = 75;
|
||||||
|
|
||||||
|
/** Подтверждение официального аккаунта человека. */
|
||||||
|
public static final short CONNECTION_OFFICIAL_ACCOUNT_CONFIRMED = 80;
|
||||||
|
|
||||||
|
/** Снятие подтверждения официального аккаунта человека. */
|
||||||
|
public static final short CONNECTION_OFFICIAL_ACCOUNT_UNCONFIRMED = 81;
|
||||||
|
|
||||||
/* ===================== USER_PARAM (msg_type=4) ===================== */
|
/* ===================== USER_PARAM (msg_type=4) ===================== */
|
||||||
|
|
||||||
/** Параметр профиля key/value (обе строки). */
|
/** Параметр профиля key/value (обе строки). */
|
||||||
|
|||||||
@@ -0,0 +1,381 @@
|
|||||||
|
BEGIN;
|
||||||
|
|
||||||
|
-- Add active FRIEND 14/15 and OFFICIAL_ACCOUNT confirmation 80/81 to connection state.
|
||||||
|
-- Legacy 60/61 remain accepted at protocol level; this migration does not reinterpret existing rows.
|
||||||
|
|
||||||
|
CREATE OR REPLACE FUNCTION shine_blocks_connection_state_ai()
|
||||||
|
RETURNS TRIGGER
|
||||||
|
LANGUAGE plpgsql
|
||||||
|
AS $$
|
||||||
|
DECLARE
|
||||||
|
resolved_login TEXT;
|
||||||
|
positive_rel_type INTEGER;
|
||||||
|
existed_before BOOLEAN;
|
||||||
|
target_channel_type INTEGER;
|
||||||
|
BEGIN
|
||||||
|
IF NEW.msg_type <> 3 THEN
|
||||||
|
RETURN NEW;
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
resolved_login := shine_resolve_login(NEW.to_login, NEW.to_bch_name);
|
||||||
|
|
||||||
|
IF NEW.msg_sub_type IN (10, 14, 20, 30, 40, 50, 52, 54, 60, 70, 74, 80) THEN
|
||||||
|
IF resolved_login IS NULL OR NEW.to_bch_name IS NULL THEN
|
||||||
|
RETURN NEW;
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
SELECT EXISTS (
|
||||||
|
SELECT 1
|
||||||
|
FROM connections_state
|
||||||
|
WHERE login = NEW.login
|
||||||
|
AND rel_type = NEW.msg_sub_type
|
||||||
|
AND to_login = resolved_login
|
||||||
|
AND to_bch_name = NEW.to_bch_name
|
||||||
|
AND to_block_number = COALESCE(NEW.to_block_number, 0)
|
||||||
|
AND to_block_hash = COALESCE(NEW.to_block_hash, decode(repeat('00', 32), 'hex'))
|
||||||
|
)
|
||||||
|
INTO existed_before;
|
||||||
|
|
||||||
|
IF NOT existed_before THEN
|
||||||
|
IF NEW.msg_sub_type = 10 THEN
|
||||||
|
INSERT INTO user_stats_state (
|
||||||
|
login,
|
||||||
|
owned_public_channels_count,
|
||||||
|
following_users_count,
|
||||||
|
following_channels_count,
|
||||||
|
close_friends_count,
|
||||||
|
updated_at_ms
|
||||||
|
) VALUES (
|
||||||
|
NEW.login,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
CAST(EXTRACT(EPOCH FROM clock_timestamp()) * 1000 AS BIGINT)
|
||||||
|
)
|
||||||
|
ON CONFLICT (login) DO UPDATE SET
|
||||||
|
close_friends_count = user_stats_state.close_friends_count + 1,
|
||||||
|
updated_at_ms = EXCLUDED.updated_at_ms;
|
||||||
|
ELSIF NEW.msg_sub_type = 30 THEN
|
||||||
|
IF NEW.to_block_number IS NULL THEN
|
||||||
|
INSERT INTO user_stats_state (
|
||||||
|
login,
|
||||||
|
owned_public_channels_count,
|
||||||
|
following_users_count,
|
||||||
|
following_channels_count,
|
||||||
|
close_friends_count,
|
||||||
|
updated_at_ms
|
||||||
|
) VALUES (
|
||||||
|
NEW.login,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
CAST(EXTRACT(EPOCH FROM clock_timestamp()) * 1000 AS BIGINT)
|
||||||
|
)
|
||||||
|
ON CONFLICT (login) DO UPDATE SET
|
||||||
|
following_channels_count = user_stats_state.following_channels_count + 1,
|
||||||
|
updated_at_ms = EXCLUDED.updated_at_ms;
|
||||||
|
ELSIF NEW.to_block_number = 0 THEN
|
||||||
|
INSERT INTO user_stats_state (
|
||||||
|
login,
|
||||||
|
owned_public_channels_count,
|
||||||
|
following_users_count,
|
||||||
|
following_channels_count,
|
||||||
|
close_friends_count,
|
||||||
|
updated_at_ms
|
||||||
|
) VALUES (
|
||||||
|
NEW.login,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
CAST(EXTRACT(EPOCH FROM clock_timestamp()) * 1000 AS BIGINT)
|
||||||
|
)
|
||||||
|
ON CONFLICT (login) DO UPDATE SET
|
||||||
|
following_users_count = user_stats_state.following_users_count + 1,
|
||||||
|
updated_at_ms = EXCLUDED.updated_at_ms;
|
||||||
|
ELSE
|
||||||
|
SELECT cn.channel_type_code
|
||||||
|
INTO target_channel_type
|
||||||
|
FROM channel_names_state cn
|
||||||
|
WHERE cn.owner_bch_name = NEW.to_bch_name
|
||||||
|
AND cn.channel_root_block_number = NEW.to_block_number
|
||||||
|
AND cn.channel_root_block_hash = NEW.to_block_hash
|
||||||
|
LIMIT 1;
|
||||||
|
|
||||||
|
IF target_channel_type = 1 THEN
|
||||||
|
INSERT INTO user_stats_state (
|
||||||
|
login,
|
||||||
|
owned_public_channels_count,
|
||||||
|
following_users_count,
|
||||||
|
following_channels_count,
|
||||||
|
close_friends_count,
|
||||||
|
updated_at_ms
|
||||||
|
) VALUES (
|
||||||
|
NEW.login,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
CAST(EXTRACT(EPOCH FROM clock_timestamp()) * 1000 AS BIGINT)
|
||||||
|
)
|
||||||
|
ON CONFLICT (login) DO UPDATE SET
|
||||||
|
following_channels_count = user_stats_state.following_channels_count + 1,
|
||||||
|
updated_at_ms = EXCLUDED.updated_at_ms;
|
||||||
|
|
||||||
|
INSERT INTO channel_stats_state (
|
||||||
|
owner_bch_name,
|
||||||
|
channel_root_block_number,
|
||||||
|
channel_root_block_hash,
|
||||||
|
owner_login,
|
||||||
|
channel_type_code,
|
||||||
|
subscribers_count,
|
||||||
|
updated_at_ms
|
||||||
|
) VALUES (
|
||||||
|
NEW.to_bch_name,
|
||||||
|
NEW.to_block_number,
|
||||||
|
NEW.to_block_hash,
|
||||||
|
resolved_login,
|
||||||
|
target_channel_type,
|
||||||
|
1,
|
||||||
|
CAST(EXTRACT(EPOCH FROM clock_timestamp()) * 1000 AS BIGINT)
|
||||||
|
)
|
||||||
|
ON CONFLICT (owner_bch_name, channel_root_block_number, channel_root_block_hash) DO UPDATE SET
|
||||||
|
owner_login = EXCLUDED.owner_login,
|
||||||
|
channel_type_code = EXCLUDED.channel_type_code,
|
||||||
|
subscribers_count = channel_stats_state.subscribers_count + 1,
|
||||||
|
updated_at_ms = EXCLUDED.updated_at_ms;
|
||||||
|
ELSIF target_channel_type IS NULL THEN
|
||||||
|
INSERT INTO user_stats_state (
|
||||||
|
login,
|
||||||
|
owned_public_channels_count,
|
||||||
|
following_users_count,
|
||||||
|
following_channels_count,
|
||||||
|
close_friends_count,
|
||||||
|
updated_at_ms
|
||||||
|
) VALUES (
|
||||||
|
NEW.login,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
CAST(EXTRACT(EPOCH FROM clock_timestamp()) * 1000 AS BIGINT)
|
||||||
|
)
|
||||||
|
ON CONFLICT (login) DO UPDATE SET
|
||||||
|
following_channels_count = user_stats_state.following_channels_count + 1,
|
||||||
|
updated_at_ms = EXCLUDED.updated_at_ms;
|
||||||
|
END IF;
|
||||||
|
END IF;
|
||||||
|
END IF;
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
DELETE FROM connections_state
|
||||||
|
WHERE login = NEW.login
|
||||||
|
AND rel_type = NEW.msg_sub_type
|
||||||
|
AND to_login = resolved_login
|
||||||
|
AND to_bch_name = NEW.to_bch_name
|
||||||
|
AND to_block_number = COALESCE(NEW.to_block_number, 0)
|
||||||
|
AND to_block_hash = COALESCE(NEW.to_block_hash, decode(repeat('00', 32), 'hex'));
|
||||||
|
|
||||||
|
INSERT INTO connections_state (
|
||||||
|
login, rel_type, to_login, to_bch_name, to_block_number, to_block_hash
|
||||||
|
) VALUES (
|
||||||
|
NEW.login,
|
||||||
|
NEW.msg_sub_type,
|
||||||
|
resolved_login,
|
||||||
|
NEW.to_bch_name,
|
||||||
|
COALESCE(NEW.to_block_number, 0),
|
||||||
|
COALESCE(NEW.to_block_hash, decode(repeat('00', 32), 'hex'))
|
||||||
|
);
|
||||||
|
|
||||||
|
RETURN NEW;
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
positive_rel_type := CASE NEW.msg_sub_type
|
||||||
|
WHEN 11 THEN 10
|
||||||
|
WHEN 15 THEN 14
|
||||||
|
WHEN 21 THEN 20
|
||||||
|
WHEN 31 THEN 30
|
||||||
|
WHEN 41 THEN 40
|
||||||
|
WHEN 51 THEN 50
|
||||||
|
WHEN 53 THEN 52
|
||||||
|
WHEN 55 THEN 54
|
||||||
|
WHEN 61 THEN 60
|
||||||
|
WHEN 71 THEN 70
|
||||||
|
WHEN 75 THEN 74
|
||||||
|
WHEN 81 THEN 80
|
||||||
|
ELSE NULL
|
||||||
|
END;
|
||||||
|
|
||||||
|
IF positive_rel_type IS NULL OR resolved_login IS NULL THEN
|
||||||
|
RETURN NEW;
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
SELECT EXISTS (
|
||||||
|
SELECT 1
|
||||||
|
FROM connections_state
|
||||||
|
WHERE login = NEW.login
|
||||||
|
AND rel_type = positive_rel_type
|
||||||
|
AND to_login = resolved_login
|
||||||
|
AND to_bch_name = NEW.to_bch_name
|
||||||
|
AND to_block_number = COALESCE(NEW.to_block_number, 0)
|
||||||
|
AND to_block_hash = COALESCE(NEW.to_block_hash, decode(repeat('00', 32), 'hex'))
|
||||||
|
)
|
||||||
|
INTO existed_before;
|
||||||
|
|
||||||
|
IF NOT existed_before THEN
|
||||||
|
RETURN NEW;
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
IF positive_rel_type = 10 THEN
|
||||||
|
INSERT INTO user_stats_state (
|
||||||
|
login,
|
||||||
|
owned_public_channels_count,
|
||||||
|
following_users_count,
|
||||||
|
following_channels_count,
|
||||||
|
close_friends_count,
|
||||||
|
updated_at_ms
|
||||||
|
) VALUES (
|
||||||
|
NEW.login,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
CAST(EXTRACT(EPOCH FROM clock_timestamp()) * 1000 AS BIGINT)
|
||||||
|
)
|
||||||
|
ON CONFLICT (login) DO UPDATE SET
|
||||||
|
close_friends_count = GREATEST(0, user_stats_state.close_friends_count - 1),
|
||||||
|
updated_at_ms = EXCLUDED.updated_at_ms;
|
||||||
|
ELSIF positive_rel_type = 30 THEN
|
||||||
|
IF NEW.to_block_number IS NULL THEN
|
||||||
|
INSERT INTO user_stats_state (
|
||||||
|
login,
|
||||||
|
owned_public_channels_count,
|
||||||
|
following_users_count,
|
||||||
|
following_channels_count,
|
||||||
|
close_friends_count,
|
||||||
|
updated_at_ms
|
||||||
|
) VALUES (
|
||||||
|
NEW.login,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
CAST(EXTRACT(EPOCH FROM clock_timestamp()) * 1000 AS BIGINT)
|
||||||
|
)
|
||||||
|
ON CONFLICT (login) DO UPDATE SET
|
||||||
|
following_channels_count = GREATEST(0, user_stats_state.following_channels_count - 1),
|
||||||
|
updated_at_ms = EXCLUDED.updated_at_ms;
|
||||||
|
ELSIF NEW.to_block_number = 0 THEN
|
||||||
|
INSERT INTO user_stats_state (
|
||||||
|
login,
|
||||||
|
owned_public_channels_count,
|
||||||
|
following_users_count,
|
||||||
|
following_channels_count,
|
||||||
|
close_friends_count,
|
||||||
|
updated_at_ms
|
||||||
|
) VALUES (
|
||||||
|
NEW.login,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
CAST(EXTRACT(EPOCH FROM clock_timestamp()) * 1000 AS BIGINT)
|
||||||
|
)
|
||||||
|
ON CONFLICT (login) DO UPDATE SET
|
||||||
|
following_users_count = GREATEST(0, user_stats_state.following_users_count - 1),
|
||||||
|
updated_at_ms = EXCLUDED.updated_at_ms;
|
||||||
|
ELSE
|
||||||
|
SELECT cn.channel_type_code
|
||||||
|
INTO target_channel_type
|
||||||
|
FROM channel_names_state cn
|
||||||
|
WHERE cn.owner_bch_name = NEW.to_bch_name
|
||||||
|
AND cn.channel_root_block_number = NEW.to_block_number
|
||||||
|
AND cn.channel_root_block_hash = NEW.to_block_hash
|
||||||
|
LIMIT 1;
|
||||||
|
|
||||||
|
IF target_channel_type = 1 THEN
|
||||||
|
INSERT INTO user_stats_state (
|
||||||
|
login,
|
||||||
|
owned_public_channels_count,
|
||||||
|
following_users_count,
|
||||||
|
following_channels_count,
|
||||||
|
close_friends_count,
|
||||||
|
updated_at_ms
|
||||||
|
) VALUES (
|
||||||
|
NEW.login,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
CAST(EXTRACT(EPOCH FROM clock_timestamp()) * 1000 AS BIGINT)
|
||||||
|
)
|
||||||
|
ON CONFLICT (login) DO UPDATE SET
|
||||||
|
following_channels_count = GREATEST(0, user_stats_state.following_channels_count - 1),
|
||||||
|
updated_at_ms = EXCLUDED.updated_at_ms;
|
||||||
|
|
||||||
|
INSERT INTO channel_stats_state (
|
||||||
|
owner_bch_name,
|
||||||
|
channel_root_block_number,
|
||||||
|
channel_root_block_hash,
|
||||||
|
owner_login,
|
||||||
|
channel_type_code,
|
||||||
|
subscribers_count,
|
||||||
|
updated_at_ms
|
||||||
|
) VALUES (
|
||||||
|
NEW.to_bch_name,
|
||||||
|
NEW.to_block_number,
|
||||||
|
NEW.to_block_hash,
|
||||||
|
resolved_login,
|
||||||
|
target_channel_type,
|
||||||
|
0,
|
||||||
|
CAST(EXTRACT(EPOCH FROM clock_timestamp()) * 1000 AS BIGINT)
|
||||||
|
)
|
||||||
|
ON CONFLICT (owner_bch_name, channel_root_block_number, channel_root_block_hash) DO UPDATE SET
|
||||||
|
owner_login = EXCLUDED.owner_login,
|
||||||
|
channel_type_code = EXCLUDED.channel_type_code,
|
||||||
|
subscribers_count = GREATEST(0, channel_stats_state.subscribers_count - 1),
|
||||||
|
updated_at_ms = EXCLUDED.updated_at_ms;
|
||||||
|
ELSIF target_channel_type IS NULL THEN
|
||||||
|
INSERT INTO user_stats_state (
|
||||||
|
login,
|
||||||
|
owned_public_channels_count,
|
||||||
|
following_users_count,
|
||||||
|
following_channels_count,
|
||||||
|
close_friends_count,
|
||||||
|
updated_at_ms
|
||||||
|
) VALUES (
|
||||||
|
NEW.login,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
CAST(EXTRACT(EPOCH FROM clock_timestamp()) * 1000 AS BIGINT)
|
||||||
|
)
|
||||||
|
ON CONFLICT (login) DO UPDATE SET
|
||||||
|
following_channels_count = GREATEST(0, user_stats_state.following_channels_count - 1),
|
||||||
|
updated_at_ms = EXCLUDED.updated_at_ms;
|
||||||
|
END IF;
|
||||||
|
END IF;
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
DELETE FROM connections_state
|
||||||
|
WHERE login = NEW.login
|
||||||
|
AND rel_type = positive_rel_type
|
||||||
|
AND to_login = resolved_login
|
||||||
|
AND to_bch_name = NEW.to_bch_name
|
||||||
|
AND to_block_number = COALESCE(NEW.to_block_number, 0)
|
||||||
|
AND to_block_hash = COALESCE(NEW.to_block_hash, decode(repeat('00', 32), 'hex'));
|
||||||
|
|
||||||
|
RETURN NEW;
|
||||||
|
END;
|
||||||
|
$$;
|
||||||
|
|
||||||
|
INSERT INTO db_schema_version (id, schema_version, updated_at_ms)
|
||||||
|
VALUES (1, 17, CAST(EXTRACT(EPOCH FROM clock_timestamp()) * 1000 AS BIGINT))
|
||||||
|
ON CONFLICT (id) DO UPDATE SET
|
||||||
|
schema_version = EXCLUDED.schema_version,
|
||||||
|
updated_at_ms = EXCLUDED.updated_at_ms;
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
@@ -1113,7 +1113,7 @@ BEGIN
|
|||||||
|
|
||||||
resolved_login := shine_resolve_login(NEW.to_login, NEW.to_bch_name);
|
resolved_login := shine_resolve_login(NEW.to_login, NEW.to_bch_name);
|
||||||
|
|
||||||
IF NEW.msg_sub_type IN (10, 20, 30, 40, 50, 52, 54, 60, 70, 74) THEN
|
IF NEW.msg_sub_type IN (10, 14, 20, 30, 40, 50, 52, 54, 60, 70, 74, 80) THEN
|
||||||
IF resolved_login IS NULL OR NEW.to_bch_name IS NULL THEN
|
IF resolved_login IS NULL OR NEW.to_bch_name IS NULL THEN
|
||||||
RETURN NEW;
|
RETURN NEW;
|
||||||
END IF;
|
END IF;
|
||||||
@@ -1288,6 +1288,7 @@ BEGIN
|
|||||||
|
|
||||||
positive_rel_type := CASE NEW.msg_sub_type
|
positive_rel_type := CASE NEW.msg_sub_type
|
||||||
WHEN 11 THEN 10
|
WHEN 11 THEN 10
|
||||||
|
WHEN 15 THEN 14
|
||||||
WHEN 21 THEN 20
|
WHEN 21 THEN 20
|
||||||
WHEN 31 THEN 30
|
WHEN 31 THEN 30
|
||||||
WHEN 41 THEN 40
|
WHEN 41 THEN 40
|
||||||
@@ -1297,6 +1298,7 @@ BEGIN
|
|||||||
WHEN 61 THEN 60
|
WHEN 61 THEN 60
|
||||||
WHEN 71 THEN 70
|
WHEN 71 THEN 70
|
||||||
WHEN 75 THEN 74
|
WHEN 75 THEN 74
|
||||||
|
WHEN 81 THEN 80
|
||||||
ELSE NULL
|
ELSE NULL
|
||||||
END;
|
END;
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -885,10 +885,10 @@ public final class Net_AddBlock_Handler implements JsonMessageHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Connection notifications are intentionally modeled as a generic kind.
|
// Connection notifications are intentionally modeled as a generic kind.
|
||||||
// Today only CONNECTION_CLOSE_FRIEND is indexed; future incoming connection types
|
// Current UI surfaces FRIEND and CLOSE_FRIEND here; other reserved relation types stay silent.
|
||||||
// can reuse the same notification kind and expose their code via sourceMsgSubType.
|
|
||||||
if (msgType == 3
|
if (msgType == 3
|
||||||
&& msgSubType == (MsgSubType.CONNECTION_CLOSE_FRIEND & 0xFFFF)
|
&& (msgSubType == (MsgSubType.CONNECTION_CLOSE_FRIEND & 0xFFFF)
|
||||||
|
|| msgSubType == (MsgSubType.CONNECTION_FRIEND & 0xFFFF))
|
||||||
&& block.body instanceof ConnectionBody) {
|
&& block.body instanceof ConnectionBody) {
|
||||||
UserNotificationEntry entry = baseNotificationEntry(storedEntry, ownerLogin, createdAtMs, msgSubType);
|
UserNotificationEntry entry = baseNotificationEntry(storedEntry, ownerLogin, createdAtMs, msgSubType);
|
||||||
entry.setNotificationKind("connection");
|
entry.setNotificationKind("connection");
|
||||||
|
|||||||
+15
-6
@@ -46,8 +46,10 @@ public class Net_GetUserConnectionsGraph_Handler implements JsonMessageHandler {
|
|||||||
return NetExceptionResponseFactory.error(req, 404, "USER_NOT_FOUND", "Пользователь не найден");
|
return NetExceptionResponseFactory.error(req, 404, "USER_NOT_FOUND", "Пользователь не найден");
|
||||||
}
|
}
|
||||||
|
|
||||||
List<String> outFriends = ConnectionsStateDAO.getInstance().listOutgoingByRelTypeCanonical(c, canonicalLogin, MsgSubType.CONNECTION_CLOSE_FRIEND);
|
List<String> outFriends = ConnectionsStateDAO.getInstance().listOutgoingByRelTypeCanonical(c, canonicalLogin, MsgSubType.CONNECTION_FRIEND);
|
||||||
List<String> inFriends = ConnectionsStateDAO.getInstance().listIncomingByRelTypeCanonical(c, canonicalLogin, MsgSubType.CONNECTION_CLOSE_FRIEND);
|
List<String> inFriends = ConnectionsStateDAO.getInstance().listIncomingByRelTypeCanonical(c, canonicalLogin, MsgSubType.CONNECTION_FRIEND);
|
||||||
|
List<String> outCloseFriends = ConnectionsStateDAO.getInstance().listOutgoingByRelTypeCanonical(c, canonicalLogin, MsgSubType.CONNECTION_CLOSE_FRIEND);
|
||||||
|
List<String> inCloseFriends = ConnectionsStateDAO.getInstance().listIncomingByRelTypeCanonical(c, canonicalLogin, MsgSubType.CONNECTION_CLOSE_FRIEND);
|
||||||
List<String> outContacts = ConnectionsStateDAO.getInstance().listOutgoingByRelTypeCanonical(c, canonicalLogin, MsgSubType.CONNECTION_CONTACT);
|
List<String> outContacts = ConnectionsStateDAO.getInstance().listOutgoingByRelTypeCanonical(c, canonicalLogin, MsgSubType.CONNECTION_CONTACT);
|
||||||
List<String> inContacts = ConnectionsStateDAO.getInstance().listIncomingByRelTypeCanonical(c, canonicalLogin, MsgSubType.CONNECTION_CONTACT);
|
List<String> inContacts = ConnectionsStateDAO.getInstance().listIncomingByRelTypeCanonical(c, canonicalLogin, MsgSubType.CONNECTION_CONTACT);
|
||||||
List<String> outFollows = ConnectionsStateDAO.getInstance().listOutgoingByRelTypeCanonical(c, canonicalLogin, MsgSubType.CONNECTION_FOLLOW);
|
List<String> outFollows = ConnectionsStateDAO.getInstance().listOutgoingByRelTypeCanonical(c, canonicalLogin, MsgSubType.CONNECTION_FOLLOW);
|
||||||
@@ -60,8 +62,11 @@ public class Net_GetUserConnectionsGraph_Handler implements JsonMessageHandler {
|
|||||||
List<String> inChildren = ConnectionsStateDAO.getInstance().listIncomingByRelTypeCanonical(c, canonicalLogin, MsgSubType.CONNECTION_CHILD);
|
List<String> inChildren = ConnectionsStateDAO.getInstance().listIncomingByRelTypeCanonical(c, canonicalLogin, MsgSubType.CONNECTION_CHILD);
|
||||||
List<String> outSiblings = ConnectionsStateDAO.getInstance().listOutgoingByRelTypeCanonical(c, canonicalLogin, MsgSubType.CONNECTION_SIBLING);
|
List<String> outSiblings = ConnectionsStateDAO.getInstance().listOutgoingByRelTypeCanonical(c, canonicalLogin, MsgSubType.CONNECTION_SIBLING);
|
||||||
List<String> inSiblings = ConnectionsStateDAO.getInstance().listIncomingByRelTypeCanonical(c, canonicalLogin, MsgSubType.CONNECTION_SIBLING);
|
List<String> inSiblings = ConnectionsStateDAO.getInstance().listIncomingByRelTypeCanonical(c, canonicalLogin, MsgSubType.CONNECTION_SIBLING);
|
||||||
List<String> outKnownPersons = ConnectionsStateDAO.getInstance().listOutgoingByRelTypeCanonical(c, canonicalLogin, MsgSubType.CONNECTION_KNOWN_PERSON);
|
// Legacy 60/61 are accepted by the protocol but intentionally not surfaced by current UI.
|
||||||
List<String> inKnownPersons = ConnectionsStateDAO.getInstance().listIncomingByRelTypeCanonical(c, canonicalLogin, MsgSubType.CONNECTION_KNOWN_PERSON);
|
List<String> outKnownPersons = List.of();
|
||||||
|
List<String> inKnownPersons = List.of();
|
||||||
|
List<String> outOfficialAccounts = ConnectionsStateDAO.getInstance().listOutgoingByRelTypeCanonical(c, canonicalLogin, MsgSubType.CONNECTION_OFFICIAL_ACCOUNT_CONFIRMED);
|
||||||
|
List<String> inOfficialAccounts = ConnectionsStateDAO.getInstance().listIncomingByRelTypeCanonical(c, canonicalLogin, MsgSubType.CONNECTION_OFFICIAL_ACCOUNT_CONFIRMED);
|
||||||
List<String> outShineConfirmed = ConnectionsStateDAO.getInstance().listOutgoingByRelTypeCanonical(c, canonicalLogin, MsgSubType.CONNECTION_SHINE_CONFIRMED);
|
List<String> outShineConfirmed = ConnectionsStateDAO.getInstance().listOutgoingByRelTypeCanonical(c, canonicalLogin, MsgSubType.CONNECTION_SHINE_CONFIRMED);
|
||||||
List<String> inShineConfirmed = ConnectionsStateDAO.getInstance().listIncomingByRelTypeCanonical(c, canonicalLogin, MsgSubType.CONNECTION_SHINE_CONFIRMED);
|
List<String> inShineConfirmed = ConnectionsStateDAO.getInstance().listIncomingByRelTypeCanonical(c, canonicalLogin, MsgSubType.CONNECTION_SHINE_CONFIRMED);
|
||||||
List<String> outShineSeen = ConnectionsStateDAO.getInstance().listOutgoingByRelTypeCanonical(c, canonicalLogin, MsgSubType.CONNECTION_SHINE_SEEN);
|
List<String> outShineSeen = ConnectionsStateDAO.getInstance().listOutgoingByRelTypeCanonical(c, canonicalLogin, MsgSubType.CONNECTION_SHINE_SEEN);
|
||||||
@@ -69,9 +74,9 @@ public class Net_GetUserConnectionsGraph_Handler implements JsonMessageHandler {
|
|||||||
|
|
||||||
LinkedHashSet<String> allLogins = new LinkedHashSet<>();
|
LinkedHashSet<String> allLogins = new LinkedHashSet<>();
|
||||||
allLogins.add(canonicalLogin);
|
allLogins.add(canonicalLogin);
|
||||||
addAllLogins(allLogins, outFriends, inFriends, outContacts, inContacts, outFollows, inFollows,
|
addAllLogins(allLogins, outFriends, inFriends, outCloseFriends, inCloseFriends, outContacts, inContacts, outFollows, inFollows,
|
||||||
outSpouses, inSpouses, outParents, inParents, outChildren, inChildren, outSiblings, inSiblings,
|
outSpouses, inSpouses, outParents, inParents, outChildren, inChildren, outSiblings, inSiblings,
|
||||||
outKnownPersons, inKnownPersons, outShineConfirmed, inShineConfirmed, outShineSeen, inShineSeen);
|
outKnownPersons, inKnownPersons, outOfficialAccounts, inOfficialAccounts, outShineConfirmed, inShineConfirmed, outShineSeen, inShineSeen);
|
||||||
|
|
||||||
Map<String, UserMeta> metaByLogin = loadUserMeta(c, allLogins);
|
Map<String, UserMeta> metaByLogin = loadUserMeta(c, allLogins);
|
||||||
List<String> spouseLogins = mergeUnique(outSpouses, inSpouses);
|
List<String> spouseLogins = mergeUnique(outSpouses, inSpouses);
|
||||||
@@ -86,6 +91,8 @@ public class Net_GetUserConnectionsGraph_Handler implements JsonMessageHandler {
|
|||||||
resp.setLogin(canonicalLogin);
|
resp.setLogin(canonicalLogin);
|
||||||
resp.setOutFriends(outFriends);
|
resp.setOutFriends(outFriends);
|
||||||
resp.setInFriends(inFriends);
|
resp.setInFriends(inFriends);
|
||||||
|
resp.setOutCloseFriends(outCloseFriends);
|
||||||
|
resp.setInCloseFriends(inCloseFriends);
|
||||||
resp.setOutContacts(outContacts);
|
resp.setOutContacts(outContacts);
|
||||||
resp.setInContacts(inContacts);
|
resp.setInContacts(inContacts);
|
||||||
resp.setOutFollows(outFollows);
|
resp.setOutFollows(outFollows);
|
||||||
@@ -100,6 +107,8 @@ public class Net_GetUserConnectionsGraph_Handler implements JsonMessageHandler {
|
|||||||
resp.setInSiblings(inSiblings);
|
resp.setInSiblings(inSiblings);
|
||||||
resp.setOutKnownPersons(outKnownPersons);
|
resp.setOutKnownPersons(outKnownPersons);
|
||||||
resp.setInKnownPersons(inKnownPersons);
|
resp.setInKnownPersons(inKnownPersons);
|
||||||
|
resp.setOutOfficialAccounts(outOfficialAccounts);
|
||||||
|
resp.setInOfficialAccounts(inOfficialAccounts);
|
||||||
resp.setOutShineConfirmed(outShineConfirmed);
|
resp.setOutShineConfirmed(outShineConfirmed);
|
||||||
resp.setInShineConfirmed(inShineConfirmed);
|
resp.setInShineConfirmed(inShineConfirmed);
|
||||||
resp.setOutShineSeen(outShineSeen);
|
resp.setOutShineSeen(outShineSeen);
|
||||||
|
|||||||
+12
@@ -9,6 +9,8 @@ public class Net_GetUserConnectionsGraph_Response extends Net_Response {
|
|||||||
private String login;
|
private String login;
|
||||||
private List<String> outFriends = new ArrayList<>();
|
private List<String> outFriends = new ArrayList<>();
|
||||||
private List<String> inFriends = new ArrayList<>();
|
private List<String> inFriends = new ArrayList<>();
|
||||||
|
private List<String> outCloseFriends = new ArrayList<>();
|
||||||
|
private List<String> inCloseFriends = new ArrayList<>();
|
||||||
private List<String> outContacts = new ArrayList<>();
|
private List<String> outContacts = new ArrayList<>();
|
||||||
private List<String> inContacts = new ArrayList<>();
|
private List<String> inContacts = new ArrayList<>();
|
||||||
private List<String> outFollows = new ArrayList<>();
|
private List<String> outFollows = new ArrayList<>();
|
||||||
@@ -23,6 +25,8 @@ public class Net_GetUserConnectionsGraph_Response extends Net_Response {
|
|||||||
private List<String> inSiblings = new ArrayList<>();
|
private List<String> inSiblings = new ArrayList<>();
|
||||||
private List<String> outKnownPersons = new ArrayList<>();
|
private List<String> outKnownPersons = new ArrayList<>();
|
||||||
private List<String> inKnownPersons = new ArrayList<>();
|
private List<String> inKnownPersons = new ArrayList<>();
|
||||||
|
private List<String> outOfficialAccounts = new ArrayList<>();
|
||||||
|
private List<String> inOfficialAccounts = new ArrayList<>();
|
||||||
private List<String> outShineConfirmed = new ArrayList<>();
|
private List<String> outShineConfirmed = new ArrayList<>();
|
||||||
private List<String> inShineConfirmed = new ArrayList<>();
|
private List<String> inShineConfirmed = new ArrayList<>();
|
||||||
private List<String> outShineSeen = new ArrayList<>();
|
private List<String> outShineSeen = new ArrayList<>();
|
||||||
@@ -84,6 +88,10 @@ public class Net_GetUserConnectionsGraph_Response extends Net_Response {
|
|||||||
public void setOutFriends(List<String> outFriends) { this.outFriends = outFriends; }
|
public void setOutFriends(List<String> outFriends) { this.outFriends = outFriends; }
|
||||||
public List<String> getInFriends() { return inFriends; }
|
public List<String> getInFriends() { return inFriends; }
|
||||||
public void setInFriends(List<String> inFriends) { this.inFriends = inFriends; }
|
public void setInFriends(List<String> inFriends) { this.inFriends = inFriends; }
|
||||||
|
public List<String> getOutCloseFriends() { return outCloseFriends; }
|
||||||
|
public void setOutCloseFriends(List<String> outCloseFriends) { this.outCloseFriends = outCloseFriends; }
|
||||||
|
public List<String> getInCloseFriends() { return inCloseFriends; }
|
||||||
|
public void setInCloseFriends(List<String> inCloseFriends) { this.inCloseFriends = inCloseFriends; }
|
||||||
public List<String> getOutContacts() { return outContacts; }
|
public List<String> getOutContacts() { return outContacts; }
|
||||||
public void setOutContacts(List<String> outContacts) { this.outContacts = outContacts; }
|
public void setOutContacts(List<String> outContacts) { this.outContacts = outContacts; }
|
||||||
public List<String> getInContacts() { return inContacts; }
|
public List<String> getInContacts() { return inContacts; }
|
||||||
@@ -112,6 +120,10 @@ public class Net_GetUserConnectionsGraph_Response extends Net_Response {
|
|||||||
public void setOutKnownPersons(List<String> outKnownPersons) { this.outKnownPersons = outKnownPersons; }
|
public void setOutKnownPersons(List<String> outKnownPersons) { this.outKnownPersons = outKnownPersons; }
|
||||||
public List<String> getInKnownPersons() { return inKnownPersons; }
|
public List<String> getInKnownPersons() { return inKnownPersons; }
|
||||||
public void setInKnownPersons(List<String> inKnownPersons) { this.inKnownPersons = inKnownPersons; }
|
public void setInKnownPersons(List<String> inKnownPersons) { this.inKnownPersons = inKnownPersons; }
|
||||||
|
public List<String> getOutOfficialAccounts() { return outOfficialAccounts; }
|
||||||
|
public void setOutOfficialAccounts(List<String> outOfficialAccounts) { this.outOfficialAccounts = outOfficialAccounts; }
|
||||||
|
public List<String> getInOfficialAccounts() { return inOfficialAccounts; }
|
||||||
|
public void setInOfficialAccounts(List<String> inOfficialAccounts) { this.inOfficialAccounts = inOfficialAccounts; }
|
||||||
public List<String> getOutShineConfirmed() { return outShineConfirmed; }
|
public List<String> getOutShineConfirmed() { return outShineConfirmed; }
|
||||||
public void setOutShineConfirmed(List<String> outShineConfirmed) { this.outShineConfirmed = outShineConfirmed; }
|
public void setOutShineConfirmed(List<String> outShineConfirmed) { this.outShineConfirmed = outShineConfirmed; }
|
||||||
public List<String> getInShineConfirmed() { return inShineConfirmed; }
|
public List<String> getInShineConfirmed() { return inShineConfirmed; }
|
||||||
|
|||||||
+2
-2
@@ -1,2 +1,2 @@
|
|||||||
client.version=1.10.0
|
client.version=1.10.1
|
||||||
server.version=1.8.0
|
server.version=1.8.1
|
||||||
|
|||||||
@@ -132,6 +132,8 @@
|
|||||||
"login": "Alice",
|
"login": "Alice",
|
||||||
"outFriends": ["Bob"],
|
"outFriends": ["Bob"],
|
||||||
"inFriends": ["Kate"],
|
"inFriends": ["Kate"],
|
||||||
|
"outCloseFriends": [],
|
||||||
|
"inCloseFriends": [],
|
||||||
"outContacts": [],
|
"outContacts": [],
|
||||||
"inContacts": [],
|
"inContacts": [],
|
||||||
"outFollows": [],
|
"outFollows": [],
|
||||||
@@ -146,6 +148,8 @@
|
|||||||
"inSiblings": [],
|
"inSiblings": [],
|
||||||
"outKnownPersons": [],
|
"outKnownPersons": [],
|
||||||
"inKnownPersons": [],
|
"inKnownPersons": [],
|
||||||
|
"outOfficialAccounts": [],
|
||||||
|
"inOfficialAccounts": [],
|
||||||
"outShineConfirmed": [],
|
"outShineConfirmed": [],
|
||||||
"inShineConfirmed": [],
|
"inShineConfirmed": [],
|
||||||
"outShineSeen": [],
|
"outShineSeen": [],
|
||||||
@@ -171,6 +175,7 @@
|
|||||||
### Примечание
|
### Примечание
|
||||||
|
|
||||||
Поля `known_person`, `shine_confirmed`, `shine_seen` в UI считаются недопроверенной зоной проекта; при изменениях этой логики нужна ручная end-to-end проверка.
|
Поля `known_person`, `shine_confirmed`, `shine_seen` в UI считаются недопроверенной зоной проекта; при изменениях этой логики нужна ручная end-to-end проверка.
|
||||||
|
`outCloseFriends` / `inCloseFriends` возвращают близких друзей, а `outOfficialAccounts` / `inOfficialAccounts` - подтверждённые официальные аккаунты.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -104,10 +104,8 @@ function applyRelativeGender(map, rows) {
|
|||||||
|
|
||||||
function getRelativeGenderMap(graph) {
|
function getRelativeGenderMap(graph) {
|
||||||
const map = new Map();
|
const map = new Map();
|
||||||
applyRelativeGender(map, graph?.parents);
|
// Родственные связи пока скрыты из UI, хотя сервер продолжает хранить их коды.
|
||||||
applyRelativeGender(map, graph?.children);
|
void graph;
|
||||||
applyRelativeGender(map, graph?.siblings);
|
|
||||||
applyRelativeGender(map, graph?.spouses);
|
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,6 +113,8 @@ function buildGraphModel(graph, centerLogin) {
|
|||||||
const login = normalizeLogin(graph?.login || centerLogin || state.session.login);
|
const login = normalizeLogin(graph?.login || centerLogin || state.session.login);
|
||||||
const outFriends = toSet(graph?.outFriends);
|
const outFriends = toSet(graph?.outFriends);
|
||||||
const inFriends = toSet(graph?.inFriends);
|
const inFriends = toSet(graph?.inFriends);
|
||||||
|
const outCloseFriends = toSet(graph?.outCloseFriends);
|
||||||
|
const inCloseFriends = toSet(graph?.inCloseFriends);
|
||||||
const outParents = toSet(graph?.outParents);
|
const outParents = toSet(graph?.outParents);
|
||||||
const inParents = toSet(graph?.inParents);
|
const inParents = toSet(graph?.inParents);
|
||||||
const outChildren = toSet(graph?.outChildren);
|
const outChildren = toSet(graph?.outChildren);
|
||||||
@@ -128,8 +128,8 @@ function buildGraphModel(graph, centerLogin) {
|
|||||||
const inContacts = toSet(graph?.inContacts);
|
const inContacts = toSet(graph?.inContacts);
|
||||||
const outFollows = toSet(graph?.outFollows);
|
const outFollows = toSet(graph?.outFollows);
|
||||||
const inFollows = toSet(graph?.inFollows);
|
const inFollows = toSet(graph?.inFollows);
|
||||||
const outKnown = toSet(graph?.outKnownPersons);
|
const outOfficial = toSet(graph?.outOfficialAccounts);
|
||||||
const inKnown = toSet(graph?.inKnownPersons);
|
const inOfficial = toSet(graph?.inOfficialAccounts);
|
||||||
|
|
||||||
const relativesGender = getRelativeGenderMap(graph);
|
const relativesGender = getRelativeGenderMap(graph);
|
||||||
const allMarks = getMarkByLogin(graph?.allUsers);
|
const allMarks = getMarkByLogin(graph?.allUsers);
|
||||||
@@ -137,67 +137,35 @@ function buildGraphModel(graph, centerLogin) {
|
|||||||
const allLogins = uniqueLogins([
|
const allLogins = uniqueLogins([
|
||||||
...(graph?.outFriends || []),
|
...(graph?.outFriends || []),
|
||||||
...(graph?.inFriends || []),
|
...(graph?.inFriends || []),
|
||||||
...(graph?.outParents || []),
|
...(graph?.outCloseFriends || []),
|
||||||
...(graph?.inParents || []),
|
...(graph?.inCloseFriends || []),
|
||||||
...(graph?.outChildren || []),
|
|
||||||
...(graph?.inChildren || []),
|
|
||||||
...(graph?.outSiblings || []),
|
|
||||||
...(graph?.inSiblings || []),
|
|
||||||
...(graph?.outSpouses || []),
|
|
||||||
...(graph?.inSpouses || []),
|
|
||||||
...(graph?.outContacts || []),
|
...(graph?.outContacts || []),
|
||||||
...(graph?.inContacts || []),
|
...(graph?.inContacts || []),
|
||||||
...(graph?.outFollows || []),
|
...(graph?.outFollows || []),
|
||||||
...(graph?.inFollows || []),
|
...(graph?.inFollows || []),
|
||||||
...(graph?.outKnownPersons || []),
|
...(graph?.outOfficialAccounts || []),
|
||||||
...(graph?.inKnownPersons || []),
|
...(graph?.inOfficialAccounts || []),
|
||||||
]).filter((entry) => normKey(entry) !== normKey(login));
|
]).filter((entry) => normKey(entry) !== normKey(login));
|
||||||
|
|
||||||
const relations = allLogins.map((targetLogin) => {
|
const relations = allLogins.map((targetLogin) => {
|
||||||
const parentOut = hasLogin(outParents, targetLogin);
|
|
||||||
const parentIn = hasLogin(inChildren, targetLogin);
|
|
||||||
const childOut = hasLogin(outChildren, targetLogin);
|
|
||||||
const childIn = hasLogin(inParents, targetLogin);
|
|
||||||
const siblingOut = hasLogin(outSiblings, targetLogin);
|
|
||||||
const siblingIn = hasLogin(inSiblings, targetLogin);
|
|
||||||
const spouseOut = hasLogin(outSpouses, targetLogin);
|
|
||||||
const spouseIn = hasLogin(inSpouses, targetLogin);
|
|
||||||
const friendOut = hasLogin(outFriends, targetLogin);
|
const friendOut = hasLogin(outFriends, targetLogin);
|
||||||
const friendIn = hasLogin(inFriends, targetLogin);
|
const friendIn = hasLogin(inFriends, targetLogin);
|
||||||
const contactOut = hasLogin(outContacts, targetLogin) || hasLogin(outFollows, targetLogin) || hasLogin(outKnown, targetLogin);
|
const closeFriendOut = hasLogin(outCloseFriends, targetLogin);
|
||||||
const contactIn = hasLogin(inContacts, targetLogin) || hasLogin(inFollows, targetLogin) || hasLogin(inKnown, targetLogin);
|
const closeFriendIn = hasLogin(inCloseFriends, targetLogin);
|
||||||
|
const contactOut = hasLogin(outContacts, targetLogin) || hasLogin(outFollows, targetLogin) || hasLogin(outOfficial, targetLogin);
|
||||||
|
const contactIn = hasLogin(inContacts, targetLogin) || hasLogin(inFollows, targetLogin) || hasLogin(inOfficial, targetLogin);
|
||||||
|
|
||||||
let role = 'contact';
|
let role = 'contact';
|
||||||
if (parentOut || parentIn) role = 'parent';
|
if (closeFriendOut || closeFriendIn || friendOut || friendIn) role = 'friend';
|
||||||
else if (childOut || childIn) role = 'child';
|
|
||||||
else if (spouseOut || spouseIn) role = 'spouse';
|
|
||||||
else if (siblingOut || siblingIn) role = 'sibling';
|
|
||||||
else if (friendOut || friendIn) role = 'friend';
|
|
||||||
|
|
||||||
let forward = friendOut;
|
let forward = role === 'friend' ? (closeFriendOut || friendOut) : contactOut;
|
||||||
let backward = friendIn;
|
let backward = role === 'friend' ? (closeFriendIn || friendIn) : contactIn;
|
||||||
if (role === 'parent') {
|
|
||||||
forward = parentOut;
|
|
||||||
backward = parentIn;
|
|
||||||
} else if (role === 'child') {
|
|
||||||
forward = childOut;
|
|
||||||
backward = childIn;
|
|
||||||
} else if (role === 'spouse') {
|
|
||||||
forward = spouseOut;
|
|
||||||
backward = spouseIn;
|
|
||||||
} else if (role === 'sibling') {
|
|
||||||
forward = siblingOut;
|
|
||||||
backward = siblingIn;
|
|
||||||
} else if (role === 'contact') {
|
|
||||||
forward = contactOut;
|
|
||||||
backward = contactIn;
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
login: targetLogin,
|
login: targetLogin,
|
||||||
key: normKey(targetLogin),
|
key: normKey(targetLogin),
|
||||||
role,
|
role,
|
||||||
isRelative: role === 'parent' || role === 'child' || role === 'spouse' || role === 'sibling',
|
isRelative: false,
|
||||||
gender: normalizeGender(relativesGender.get(normKey(targetLogin))),
|
gender: normalizeGender(relativesGender.get(normKey(targetLogin))),
|
||||||
forward: Boolean(forward),
|
forward: Boolean(forward),
|
||||||
backward: Boolean(backward),
|
backward: Boolean(backward),
|
||||||
@@ -242,11 +210,10 @@ export function render({ navigate, route, chrome } = {}) {
|
|||||||
// Фильтры слоёв (Фаза 3). Фокус всегда виден; предикат применяется к периферийным узлам.
|
// Фильтры слоёв (Фаза 3). Фокус всегда виден; предикат применяется к периферийным узлам.
|
||||||
const FILTERS = {
|
const FILTERS = {
|
||||||
all: { label: 'Все', pred: () => true },
|
all: { label: 'Все', pred: () => true },
|
||||||
family: { label: 'Семья', pred: (n) => n.relationType === 'family' },
|
|
||||||
friends: { label: 'Друзья', pred: (n) => n.relationType === 'friend' },
|
friends: { label: 'Друзья', pred: (n) => n.relationType === 'friend' },
|
||||||
shining: { label: 'Сияющие', pred: (n) => Boolean(n.shining) },
|
shining: { label: 'Сияющие', pred: (n) => Boolean(n.shining) },
|
||||||
};
|
};
|
||||||
const FILTER_ORDER = ['all', 'family', 'friends', 'shining'];
|
const FILTER_ORDER = ['all', 'friends', 'shining'];
|
||||||
let activeFilter = 'all';
|
let activeFilter = 'all';
|
||||||
const filterChips = {};
|
const filterChips = {};
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { renderHeader } from '../components/header.js';
|
import { renderHeader } from '../components/header.js';
|
||||||
import { profile } from '../mock-data.js';
|
import { profile } from '../mock-data.js';
|
||||||
import { authService, state } from '../state.js';
|
import { authService, state } from '../state.js';
|
||||||
import {
|
import {
|
||||||
@@ -38,11 +38,9 @@ const GENDER_OPTIONS = Object.freeze([
|
|||||||
{ value: PROFILE_GENDER_UNKNOWN, label: 'Не указан' },
|
{ value: PROFILE_GENDER_UNKNOWN, label: 'Не указан' },
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
// Родственные типы сохранены в протоколе, но пока намеренно скрыты из UI.
|
||||||
const RELATIVE_RELATION_OPTIONS = Object.freeze([
|
const RELATIVE_RELATION_OPTIONS = Object.freeze([
|
||||||
{ value: 'parent', label: 'Родитель (мать/отец по полу)' },
|
{ value: 'friend', label: 'Друг' },
|
||||||
{ value: 'child', label: 'Ребёнок (сын/дочь по полу)' },
|
|
||||||
{ value: 'spouse', label: 'Жена / Муж (по полу)' },
|
|
||||||
{ value: 'sibling', label: 'Брат или сестра (по полу)' },
|
|
||||||
{ value: 'close_friend', label: 'Близкий друг' },
|
{ value: 'close_friend', label: 'Близкий друг' },
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@@ -75,6 +73,7 @@ function relationAccusativeLabel(type, targetGender) {
|
|||||||
if (gender === PROFILE_GENDER_FEMALE) return 'жену';
|
if (gender === PROFILE_GENDER_FEMALE) return 'жену';
|
||||||
return 'жену/мужа';
|
return 'жену/мужа';
|
||||||
}
|
}
|
||||||
|
if (type === 'friend') return 'друга';
|
||||||
return 'близкого друга';
|
return 'близкого друга';
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -134,12 +133,12 @@ export function render({ navigate, chrome }) {
|
|||||||
const relativesCard = document.createElement('div');
|
const relativesCard = document.createElement('div');
|
||||||
relativesCard.className = 'card stack';
|
relativesCard.className = 'card stack';
|
||||||
relativesCard.innerHTML = `
|
relativesCard.innerHTML = `
|
||||||
<div class="profile-param-value"><b>Близкие родственники</b></div>
|
<div class="profile-param-value"><b>Друзья</b></div>
|
||||||
<div class="meta-muted">
|
<div class="meta-muted">
|
||||||
Добавьте связь: родитель, ребёнок, жена/муж, брат/сестра или близкий друг.
|
Добавьте пользователя в друзья или в близкие друзья.
|
||||||
Формулировка (мать/отец, брат/сестра) определяется по полу выбранного пользователя.
|
Родственные типы связей сохранены в протоколе, но пока скрыты из интерфейса.
|
||||||
</div>
|
</div>
|
||||||
<button class="secondary-btn" type="button" data-add-relative="true">Добавить близких родственников</button>
|
<button class="secondary-btn" type="button" data-add-relative="true">Добавить друга</button>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const reloadBtn = topRow.querySelector('[data-reload="true"]');
|
const reloadBtn = topRow.querySelector('[data-reload="true"]');
|
||||||
@@ -753,20 +752,16 @@ export function render({ navigate, chrome }) {
|
|||||||
status.textContent = 'Сохранение связи...';
|
status.textContent = 'Сохранение связи...';
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (relationType === 'close_friend') {
|
if (!state.session.storagePwdInMemory) {
|
||||||
await authService.addCloseFriend(targetLogin);
|
throw new Error('Нет storagePwd в памяти сессии. Выполните вход заново.');
|
||||||
} else {
|
|
||||||
if (!state.session.storagePwdInMemory) {
|
|
||||||
throw new Error('Нет storagePwd в памяти сессии. Выполните вход заново.');
|
|
||||||
}
|
|
||||||
await authService.setUserRelation({
|
|
||||||
login: sessionLogin,
|
|
||||||
toLogin: targetLogin,
|
|
||||||
kind: relationType,
|
|
||||||
enabled: true,
|
|
||||||
storagePwd: state.session.storagePwdInMemory,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
await authService.setUserRelation({
|
||||||
|
login: sessionLogin,
|
||||||
|
toLogin: targetLogin,
|
||||||
|
kind: relationType,
|
||||||
|
enabled: true,
|
||||||
|
storagePwd: state.session.storagePwdInMemory,
|
||||||
|
});
|
||||||
status.className = 'status-line is-available';
|
status.className = 'status-line is-available';
|
||||||
status.textContent = `Связь добавлена: ${targetLogin} как ${relationLabel}.`;
|
status.textContent = `Связь добавлена: ${targetLogin} как ${relationLabel}.`;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@@ -64,20 +64,29 @@ function genderText(value) {
|
|||||||
|
|
||||||
function relationButtonLabel(kind, flags) {
|
function relationButtonLabel(kind, flags) {
|
||||||
if (kind === 'contact') return flags.outContact ? 'Убрать из контактов' : 'Добавить в контакты';
|
if (kind === 'contact') return flags.outContact ? 'Убрать из контактов' : 'Добавить в контакты';
|
||||||
if (kind === 'friend') return flags.outFriend ? 'Убрать из близких друзей' : 'Добавить в близкие друзья';
|
if (kind === 'friend') return flags.outFriend ? 'Убрать из друзей' : 'Добавить в друзья';
|
||||||
return flags.outFollow ? 'Отписаться' : 'Подписаться';
|
if (kind === 'close_friend') return flags.outCloseFriend ? 'Убрать из близких друзей' : 'Добавить в близкие друзья';
|
||||||
|
if (kind === 'official_account') return flags.outOfficialAccount ? 'Снять подтверждение' : 'Подтвердить аккаунт';
|
||||||
|
if (kind === 'shine_confirmed') return flags.outShineConfirmed ? 'Снять подтверждение' : 'Подтвердить сияющего';
|
||||||
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
function relationNextState(kind, flags) {
|
function relationNextState(kind, flags) {
|
||||||
if (kind === 'contact') return !flags.outContact;
|
if (kind === 'contact') return !flags.outContact;
|
||||||
if (kind === 'friend') return !flags.outFriend;
|
if (kind === 'friend') return !flags.outFriend;
|
||||||
return !flags.outFollow;
|
if (kind === 'close_friend') return !flags.outCloseFriend;
|
||||||
|
if (kind === 'official_account') return !flags.outOfficialAccount;
|
||||||
|
if (kind === 'shine_confirmed') return !flags.outShineConfirmed;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function relationConfirmLabel(kind) {
|
function relationConfirmLabel(kind) {
|
||||||
if (kind === 'contact') return 'контакт';
|
if (kind === 'contact') return 'контакт';
|
||||||
if (kind === 'friend') return 'статус близкого друга';
|
if (kind === 'friend') return 'статус друга';
|
||||||
return 'подписку';
|
if (kind === 'close_friend') return 'статус близкого друга';
|
||||||
|
if (kind === 'official_account') return 'подтверждение официального аккаунта';
|
||||||
|
if (kind === 'shine_confirmed') return 'подтверждение сияющего';
|
||||||
|
return 'связь';
|
||||||
}
|
}
|
||||||
|
|
||||||
function relationStateText(kind, flags) {
|
function relationStateText(kind, flags) {
|
||||||
@@ -88,55 +97,49 @@ function relationStateText(kind, flags) {
|
|||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
if (kind === 'friend') {
|
if (kind === 'friend') {
|
||||||
if (flags.outFriend && flags.inFriend) return 'Вы взаимно близкие друзья.';
|
if (flags.outFriend && flags.inFriend) return 'Вы взаимно считаете друг друга друзьями.';
|
||||||
if (flags.outFriend) return 'Вы считаете этот профиль близким другом.';
|
if (flags.outFriend) return 'Вы считаете этого человека другом.';
|
||||||
if (flags.inFriend) return 'Этот профиль считает вас близким другом.';
|
if (flags.inFriend) return 'Этот человек считает вас другом.';
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
if (flags.outFollow && flags.inFollow) return 'Вы взаимно подписаны.';
|
if (kind === 'close_friend') {
|
||||||
if (flags.outFollow) return 'Вы подписаны на этот профиль.';
|
if (flags.outCloseFriend && flags.inCloseFriend) return 'Вы взаимно близкие друзья.';
|
||||||
if (flags.inFollow) return 'Этот профиль подписан на вас.';
|
if (flags.outCloseFriend) return 'Вы считаете этого человека близким другом.';
|
||||||
|
if (flags.inCloseFriend) return 'Этот человек считает вас близким другом.';
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
if (kind === 'official_account') {
|
||||||
|
return flags.outOfficialAccount
|
||||||
|
? 'Вы подтверждаете, что это действительно официальный аккаунт этого человека.'
|
||||||
|
: '';
|
||||||
|
}
|
||||||
|
if (kind === 'shine_confirmed') {
|
||||||
|
return flags.outShineConfirmed
|
||||||
|
? 'Вы подтверждаете, что этот человек сияющий.'
|
||||||
|
: '';
|
||||||
|
}
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
function opinionItemsFromFlags(flags) {
|
function renderRelations(flags) {
|
||||||
const items = [];
|
const rows = [
|
||||||
if (flags.outShineSeen) {
|
{ kind: 'contact', text: relationStateText('contact', flags), button: relationButtonLabel('contact', flags) },
|
||||||
items.push({
|
{ kind: 'friend', text: relationStateText('friend', flags), button: relationButtonLabel('friend', flags) },
|
||||||
kind: 'shine_seen',
|
{ kind: 'close_friend', text: relationStateText('close_friend', flags), button: relationButtonLabel('close_friend', flags) },
|
||||||
text: 'вы утверждаете, что очень мало знаете этого человека, но вы видели его сияющим, и всё, что вы о нём знаете, подтверждает это',
|
{ kind: 'official_account', text: relationStateText('official_account', flags), button: relationButtonLabel('official_account', flags) },
|
||||||
label: 'видел сияющим',
|
{ kind: 'shine_confirmed', text: relationStateText('shine_confirmed', flags), button: relationButtonLabel('shine_confirmed', flags) },
|
||||||
});
|
];
|
||||||
}
|
|
||||||
if (flags.outShineConfirmed) {
|
|
||||||
items.push({
|
|
||||||
kind: 'shine_confirmed',
|
|
||||||
text: 'вы утверждаете, что достаточно хорошо знаете этого человека и точно уверены, что этот человек сияющий',
|
|
||||||
label: 'точно сияющий',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (flags.outKnownPerson) {
|
|
||||||
items.push({
|
|
||||||
kind: 'known_person',
|
|
||||||
text: 'вы утверждаете, что просто знаете этого человека',
|
|
||||||
label: 'просто знаю',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return items;
|
|
||||||
}
|
|
||||||
|
|
||||||
function resolveActiveOpinionKind(flags) {
|
return `
|
||||||
if (flags.outShineSeen) return 'shine_seen';
|
<div class="card stack user-relations-list" data-profile-relations="true">
|
||||||
if (flags.outShineConfirmed) return 'shine_confirmed';
|
${rows.map((row) => `
|
||||||
if (flags.outKnownPerson) return 'known_person';
|
<div class="user-rel-row ${row.text ? '' : 'is-empty'}">
|
||||||
return '';
|
<span class="user-rel-text">${escapeHtml(row.text)}</span>
|
||||||
}
|
<button class="ghost-btn user-rel-action" type="button" data-relation-action="${row.kind}">${escapeHtml(row.button)}</button>
|
||||||
|
</div>
|
||||||
function opinionLabelByKind(kind) {
|
`).join('')}
|
||||||
if (kind === 'shine_seen') return 'мало знаком, но видел сияющим';
|
</div>
|
||||||
if (kind === 'shine_confirmed') return 'точно уверен, что сияющий';
|
`;
|
||||||
if (kind === 'known_person') return 'просто знаю человека';
|
|
||||||
return kind;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderIdentity(card) {
|
function renderIdentity(card) {
|
||||||
@@ -182,82 +185,6 @@ function renderReadOnlyBadges(card) {
|
|||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderRelations(flags) {
|
|
||||||
const rows = [
|
|
||||||
{ kind: 'contact', text: relationStateText('contact', flags), button: relationButtonLabel('contact', flags) },
|
|
||||||
{ kind: 'friend', text: relationStateText('friend', flags), button: relationButtonLabel('friend', flags) },
|
|
||||||
{ kind: 'follow', text: relationStateText('follow', flags), button: relationButtonLabel('follow', flags) },
|
|
||||||
];
|
|
||||||
const opinionItems = opinionItemsFromFlags(flags);
|
|
||||||
const hasOpinion = opinionItems.length > 0;
|
|
||||||
|
|
||||||
return `
|
|
||||||
<div class="card stack user-relations-list" data-profile-relations="true">
|
|
||||||
${rows.map((row) => `
|
|
||||||
<div class="user-rel-row ${row.text ? '' : 'is-empty'}">
|
|
||||||
<span class="user-rel-text">${escapeHtml(row.text)}</span>
|
|
||||||
<button class="ghost-btn user-rel-action" type="button" data-relation-action="${row.kind}">${escapeHtml(row.button)}</button>
|
|
||||||
</div>
|
|
||||||
`).join('')}
|
|
||||||
<div class="user-rel-opinions-wrap ${hasOpinion ? '' : 'is-empty'}">
|
|
||||||
<div class="user-rel-opinions-list">
|
|
||||||
${opinionItems.map((item) => `
|
|
||||||
<div class="user-rel-opinion-item">${escapeHtml(item.text)}</div>
|
|
||||||
`).join('')}
|
|
||||||
</div>
|
|
||||||
<div class="user-rel-opinions-hint">Добавьте одну из этих трёх формулировок.</div>
|
|
||||||
</div>
|
|
||||||
<div class="user-rel-row">
|
|
||||||
<span class="user-rel-text">${hasOpinion ? 'Мнение уже добавлено.' : 'Пока нет дополнительной связи.'}</span>
|
|
||||||
<button class="ghost-btn user-rel-action user-rel-opinion-btn" type="button" data-relation-action="opinion-menu">${hasOpinion ? 'Изменить мнение' : 'Добавить мнение'}</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
function openOpinionMenuModal({ flags, onApply }) {
|
|
||||||
const root = document.getElementById('modal-root');
|
|
||||||
if (!root) return;
|
|
||||||
const activeKind = resolveActiveOpinionKind(flags);
|
|
||||||
const items = [
|
|
||||||
{ kind: 'known_person', title: 'просто знаю человека' },
|
|
||||||
{ kind: 'shine_confirmed', title: 'точно уверен, что сияющий' },
|
|
||||||
{ kind: 'shine_seen', title: 'мало знаком, но видел сияющим' },
|
|
||||||
];
|
|
||||||
const rowsHtml = items
|
|
||||||
.filter((item) => item.kind !== activeKind)
|
|
||||||
.map((item) => `<button class="secondary-btn user-opinion-modal-btn is-add" type="button" data-opinion-kind="${item.kind}" data-opinion-mode="set">Высказать: ${item.title}</button>`)
|
|
||||||
.join('');
|
|
||||||
const removeHtml = activeKind
|
|
||||||
? `<button class="secondary-btn user-opinion-modal-btn is-remove" type="button" data-opinion-kind="${activeKind}" data-opinion-mode="remove">Убрать мнение</button>`
|
|
||||||
: '';
|
|
||||||
|
|
||||||
root.innerHTML = `
|
|
||||||
<div class="modal" id="user-opinion-modal">
|
|
||||||
<div class="modal-card stack">
|
|
||||||
<h3 class="modal-title">${activeKind ? 'Изменить мнение' : 'Добавить мнение'}</h3>
|
|
||||||
<div class="stack">${rowsHtml}${removeHtml}</div>
|
|
||||||
<button class="secondary-btn" type="button" id="user-opinion-modal-close">Закрыть</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
|
|
||||||
const close = () => { root.innerHTML = ''; };
|
|
||||||
root.querySelector('#user-opinion-modal-close')?.addEventListener('click', close);
|
|
||||||
root.querySelector('#user-opinion-modal')?.addEventListener('click', (event) => {
|
|
||||||
if (event.target?.id === 'user-opinion-modal') close();
|
|
||||||
});
|
|
||||||
root.querySelectorAll('[data-opinion-mode]').forEach((btn) => {
|
|
||||||
btn.addEventListener('click', async () => {
|
|
||||||
const nextKind = String(btn.getAttribute('data-opinion-kind') || '').trim();
|
|
||||||
const mode = String(btn.getAttribute('data-opinion-mode') || '').trim();
|
|
||||||
close();
|
|
||||||
if (!nextKind) return;
|
|
||||||
await onApply({ mode, nextKind, activeKind });
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function renderReadOnlyParams(card) {
|
function renderReadOnlyParams(card) {
|
||||||
const rows = [
|
const rows = [
|
||||||
{ label: 'Имя', value: card.firstName },
|
{ label: 'Имя', value: card.firstName },
|
||||||
@@ -310,20 +237,15 @@ export function render({ navigate, route }) {
|
|||||||
let isBusy = false;
|
let isBusy = false;
|
||||||
|
|
||||||
function syncActionButtons() {
|
function syncActionButtons() {
|
||||||
const followBtn = body.querySelector('[data-relation-action="follow"]');
|
const kinds = ['contact', 'friend', 'close_friend', 'official_account', 'shine_confirmed'];
|
||||||
const friendBtn = body.querySelector('[data-relation-action="friend"]');
|
if (!currentFlags) return;
|
||||||
const contactBtn = body.querySelector('[data-relation-action="contact"]');
|
|
||||||
const opinionBtn = body.querySelector('[data-relation-action="opinion-menu"]');
|
|
||||||
if (!followBtn || !friendBtn || !contactBtn || !opinionBtn || !currentFlags) return;
|
|
||||||
const isSelf = currentCard && currentCard.login.toLowerCase() === sessionLogin.toLowerCase();
|
const isSelf = currentCard && currentCard.login.toLowerCase() === sessionLogin.toLowerCase();
|
||||||
contactBtn.textContent = relationButtonLabel('contact', currentFlags);
|
kinds.forEach((kind) => {
|
||||||
friendBtn.textContent = relationButtonLabel('friend', currentFlags);
|
const btn = body.querySelector(`[data-relation-action="${kind}"]`);
|
||||||
followBtn.textContent = relationButtonLabel('follow', currentFlags);
|
if (!btn) return;
|
||||||
contactBtn.disabled = Boolean(isSelf);
|
btn.textContent = relationButtonLabel(kind, currentFlags);
|
||||||
friendBtn.disabled = Boolean(isSelf);
|
btn.disabled = Boolean(isSelf);
|
||||||
followBtn.disabled = Boolean(isSelf);
|
});
|
||||||
opinionBtn.textContent = opinionItemsFromFlags(currentFlags).length ? 'Изменить мнение' : 'Добавить мнение';
|
|
||||||
opinionBtn.disabled = Boolean(isSelf);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function refresh() {
|
async function refresh() {
|
||||||
@@ -384,14 +306,6 @@ export function render({ navigate, route }) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (kind === 'opinion-menu') {
|
|
||||||
openOpinionMenuModal({
|
|
||||||
flags: currentFlags,
|
|
||||||
onApply: onOpinionApply,
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const nextEnabled = relationNextState(kind, currentFlags);
|
const nextEnabled = relationNextState(kind, currentFlags);
|
||||||
const confirmed = window.confirm(
|
const confirmed = window.confirm(
|
||||||
`Изменить ${relationConfirmLabel(kind)} с пользователем ${currentCard.login}?\n` +
|
`Изменить ${relationConfirmLabel(kind)} с пользователем ${currentCard.login}?\n` +
|
||||||
@@ -420,64 +334,6 @@ export function render({ navigate, route }) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function onOpinionApply({ mode, nextKind, activeKind }) {
|
|
||||||
if (isBusy || !currentCard || !currentFlags) return;
|
|
||||||
if (!sessionLogin) {
|
|
||||||
window.alert('Для изменения связей нужен активный вход.');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!state.session.storagePwdInMemory) {
|
|
||||||
window.alert('Нет storagePwd в памяти сессии. Выполните вход заново.');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const confirmed = window.confirm(`Изменить мнение о пользователе ${currentCard.login}?`);
|
|
||||||
if (!confirmed) return;
|
|
||||||
|
|
||||||
isBusy = true;
|
|
||||||
status.className = 'status-line';
|
|
||||||
status.textContent = 'Сохранение отношения в блокчейн...';
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (activeKind) {
|
|
||||||
await authService.setUserRelation({
|
|
||||||
login: sessionLogin,
|
|
||||||
toLogin: currentCard.login,
|
|
||||||
kind: activeKind,
|
|
||||||
enabled: false,
|
|
||||||
storagePwd: state.session.storagePwdInMemory,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mode === 'set') {
|
|
||||||
await authService.setUserRelation({
|
|
||||||
login: sessionLogin,
|
|
||||||
toLogin: currentCard.login,
|
|
||||||
kind: nextKind,
|
|
||||||
enabled: true,
|
|
||||||
storagePwd: state.session.storagePwdInMemory,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
await refresh();
|
|
||||||
if (mode === 'set') {
|
|
||||||
const opinionVisible = Boolean(
|
|
||||||
currentFlags?.outKnownPerson
|
|
||||||
|| currentFlags?.outShineConfirmed
|
|
||||||
|| currentFlags?.outShineSeen,
|
|
||||||
);
|
|
||||||
if (!opinionVisible) {
|
|
||||||
await new Promise((resolve) => window.setTimeout(resolve, 350));
|
|
||||||
await refresh();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
status.className = 'status-line is-unavailable';
|
|
||||||
status.textContent = `Ошибка изменения связи: ${error.message || 'unknown'}`;
|
|
||||||
window.alert(`Не удалось изменить связь: ${error.message || 'unknown'}`);
|
|
||||||
isBusy = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
body.addEventListener('click', (event) => {
|
body.addEventListener('click', (event) => {
|
||||||
const target = event.target;
|
const target = event.target;
|
||||||
if (!(target instanceof HTMLElement)) return;
|
if (!(target instanceof HTMLElement)) return;
|
||||||
|
|||||||
@@ -90,18 +90,21 @@ const SIGNAL_TYPE_REMOTE_ADDBLOCK_REQUEST = 'remote_addblock_request';
|
|||||||
const SIGNAL_TYPE_REMOTE_ADDBLOCK_RESULT = 'remote_addblock_result';
|
const SIGNAL_TYPE_REMOTE_ADDBLOCK_RESULT = 'remote_addblock_result';
|
||||||
|
|
||||||
const CONNECTION_SUBTYPES = Object.freeze({
|
const CONNECTION_SUBTYPES = Object.freeze({
|
||||||
// Legacy alias: friend == close_friend. Оба ключа ведут на один и тот же код 10/11.
|
|
||||||
close_friend: { on: 10, off: 11 },
|
close_friend: { on: 10, off: 11 },
|
||||||
friend: { on: 10, off: 11 },
|
friend: { on: 14, off: 15 },
|
||||||
contact: { on: 20, off: 21 },
|
contact: { on: 20, off: 21 },
|
||||||
|
// Reserved: пока не используется UI.
|
||||||
follow: { on: 30, off: 31 },
|
follow: { on: 30, off: 31 },
|
||||||
|
// Reserved: семейные связи пока скрыты из UI.
|
||||||
spouse: { on: 40, off: 41 },
|
spouse: { on: 40, off: 41 },
|
||||||
parent: { on: 50, off: 51 },
|
parent: { on: 50, off: 51 },
|
||||||
child: { on: 52, off: 53 },
|
child: { on: 52, off: 53 },
|
||||||
sibling: { on: 54, off: 55 },
|
sibling: { on: 54, off: 55 },
|
||||||
known_person: { on: 60, off: 61 },
|
// Legacy 60/61 intentionally absent: старые блоки сервер принимает, новый UI их не создаёт.
|
||||||
shine_confirmed: { on: 70, off: 71 },
|
shine_confirmed: { on: 70, off: 71 },
|
||||||
|
// Reserved: пока не используется UI.
|
||||||
shine_seen: { on: 74, off: 75 },
|
shine_seen: { on: 74, off: 75 },
|
||||||
|
official_account: { on: 80, off: 81 },
|
||||||
});
|
});
|
||||||
|
|
||||||
function normalizeServerUrl(url) {
|
function normalizeServerUrl(url) {
|
||||||
|
|||||||
@@ -50,6 +50,8 @@ function readArray(payload, key) {
|
|||||||
const aliases = {
|
const aliases = {
|
||||||
outKnownPersons: ['outKnownPersons', 'outKnownPerson', 'out_known_persons'],
|
outKnownPersons: ['outKnownPersons', 'outKnownPerson', 'out_known_persons'],
|
||||||
inKnownPersons: ['inKnownPersons', 'inKnownPerson', 'in_known_persons'],
|
inKnownPersons: ['inKnownPersons', 'inKnownPerson', 'in_known_persons'],
|
||||||
|
outOfficialAccounts: ['outOfficialAccounts', 'outOfficialAccount', 'out_official_accounts'],
|
||||||
|
inOfficialAccounts: ['inOfficialAccounts', 'inOfficialAccount', 'in_official_accounts'],
|
||||||
outShineConfirmed: ['outShineConfirmed', 'outShineConfident', 'out_shine_confirmed'],
|
outShineConfirmed: ['outShineConfirmed', 'outShineConfident', 'out_shine_confirmed'],
|
||||||
inShineConfirmed: ['inShineConfirmed', 'inShineConfident', 'in_shine_confirmed'],
|
inShineConfirmed: ['inShineConfirmed', 'inShineConfident', 'in_shine_confirmed'],
|
||||||
outShineSeen: ['outShineSeen', 'out_shine_seen'],
|
outShineSeen: ['outShineSeen', 'out_shine_seen'],
|
||||||
@@ -81,6 +83,8 @@ async function buildRelationsModel(login) {
|
|||||||
return {
|
return {
|
||||||
outFriends: [],
|
outFriends: [],
|
||||||
inFriends: [],
|
inFriends: [],
|
||||||
|
outCloseFriends: [],
|
||||||
|
inCloseFriends: [],
|
||||||
outContacts: [],
|
outContacts: [],
|
||||||
inContacts: [],
|
inContacts: [],
|
||||||
outFollows: [],
|
outFollows: [],
|
||||||
@@ -93,6 +97,8 @@ async function buildRelationsModel(login) {
|
|||||||
inSiblings: [],
|
inSiblings: [],
|
||||||
outKnownPersons: [],
|
outKnownPersons: [],
|
||||||
inKnownPersons: [],
|
inKnownPersons: [],
|
||||||
|
outOfficialAccounts: [],
|
||||||
|
inOfficialAccounts: [],
|
||||||
outShineConfirmed: [],
|
outShineConfirmed: [],
|
||||||
inShineConfirmed: [],
|
inShineConfirmed: [],
|
||||||
outShineSeen: [],
|
outShineSeen: [],
|
||||||
@@ -129,6 +135,8 @@ async function buildRelationsModel(login) {
|
|||||||
return {
|
return {
|
||||||
outFriends: readArray(graph, 'outFriends') || [],
|
outFriends: readArray(graph, 'outFriends') || [],
|
||||||
inFriends: readArray(graph, 'inFriends') || [],
|
inFriends: readArray(graph, 'inFriends') || [],
|
||||||
|
outCloseFriends: readArray(graph, 'outCloseFriends') || [],
|
||||||
|
inCloseFriends: readArray(graph, 'inCloseFriends') || [],
|
||||||
outContacts,
|
outContacts,
|
||||||
inContacts: readArray(graph, 'inContacts') || [],
|
inContacts: readArray(graph, 'inContacts') || [],
|
||||||
outFollows,
|
outFollows,
|
||||||
@@ -141,6 +149,8 @@ async function buildRelationsModel(login) {
|
|||||||
inSiblings: readArray(graph, 'inSiblings') || [],
|
inSiblings: readArray(graph, 'inSiblings') || [],
|
||||||
outKnownPersons: readArray(graph, 'outKnownPersons') || [],
|
outKnownPersons: readArray(graph, 'outKnownPersons') || [],
|
||||||
inKnownPersons: readArray(graph, 'inKnownPersons') || [],
|
inKnownPersons: readArray(graph, 'inKnownPersons') || [],
|
||||||
|
outOfficialAccounts: readArray(graph, 'outOfficialAccounts') || [],
|
||||||
|
inOfficialAccounts: readArray(graph, 'inOfficialAccounts') || [],
|
||||||
outShineConfirmed: readArray(graph, 'outShineConfirmed') || [],
|
outShineConfirmed: readArray(graph, 'outShineConfirmed') || [],
|
||||||
inShineConfirmed: readArray(graph, 'inShineConfirmed') || [],
|
inShineConfirmed: readArray(graph, 'inShineConfirmed') || [],
|
||||||
outShineSeen: readArray(graph, 'outShineSeen') || [],
|
outShineSeen: readArray(graph, 'outShineSeen') || [],
|
||||||
@@ -169,6 +179,8 @@ export async function loadCurrentRelations() {
|
|||||||
return {
|
return {
|
||||||
outFriends: [],
|
outFriends: [],
|
||||||
inFriends: [],
|
inFriends: [],
|
||||||
|
outCloseFriends: [],
|
||||||
|
inCloseFriends: [],
|
||||||
outContacts: [],
|
outContacts: [],
|
||||||
inContacts: [],
|
inContacts: [],
|
||||||
outFollows: [],
|
outFollows: [],
|
||||||
@@ -181,6 +193,8 @@ export async function loadCurrentRelations() {
|
|||||||
inSiblings: [],
|
inSiblings: [],
|
||||||
outKnownPersons: [],
|
outKnownPersons: [],
|
||||||
inKnownPersons: [],
|
inKnownPersons: [],
|
||||||
|
outOfficialAccounts: [],
|
||||||
|
inOfficialAccounts: [],
|
||||||
outShineConfirmed: [],
|
outShineConfirmed: [],
|
||||||
inShineConfirmed: [],
|
inShineConfirmed: [],
|
||||||
outShineSeen: [],
|
outShineSeen: [],
|
||||||
@@ -194,6 +208,8 @@ export function relationFlagsForTarget(relations, targetLogin) {
|
|||||||
return {
|
return {
|
||||||
outFriend: listContainsLogin(relations?.outFriends, targetLogin),
|
outFriend: listContainsLogin(relations?.outFriends, targetLogin),
|
||||||
inFriend: listContainsLogin(relations?.inFriends, targetLogin),
|
inFriend: listContainsLogin(relations?.inFriends, targetLogin),
|
||||||
|
outCloseFriend: listContainsLogin(relations?.outCloseFriends, targetLogin),
|
||||||
|
inCloseFriend: listContainsLogin(relations?.inCloseFriends, targetLogin),
|
||||||
outContact: listContainsLogin(relations?.outContacts, targetLogin),
|
outContact: listContainsLogin(relations?.outContacts, targetLogin),
|
||||||
inContact: listContainsLogin(relations?.inContacts, targetLogin),
|
inContact: listContainsLogin(relations?.inContacts, targetLogin),
|
||||||
outFollow: listContainsLogin(relations?.outFollows, targetLogin),
|
outFollow: listContainsLogin(relations?.outFollows, targetLogin),
|
||||||
@@ -206,6 +222,8 @@ export function relationFlagsForTarget(relations, targetLogin) {
|
|||||||
inSibling: listContainsLogin(relations?.inSiblings, targetLogin),
|
inSibling: listContainsLogin(relations?.inSiblings, targetLogin),
|
||||||
outKnownPerson: listContainsLogin(relations?.outKnownPersons, targetLogin),
|
outKnownPerson: listContainsLogin(relations?.outKnownPersons, targetLogin),
|
||||||
inKnownPerson: listContainsLogin(relations?.inKnownPersons, targetLogin),
|
inKnownPerson: listContainsLogin(relations?.inKnownPersons, targetLogin),
|
||||||
|
outOfficialAccount: listContainsLogin(relations?.outOfficialAccounts, targetLogin),
|
||||||
|
inOfficialAccount: listContainsLogin(relations?.inOfficialAccounts, targetLogin),
|
||||||
outShineConfirmed: listContainsLogin(relations?.outShineConfirmed, targetLogin),
|
outShineConfirmed: listContainsLogin(relations?.outShineConfirmed, targetLogin),
|
||||||
inShineConfirmed: listContainsLogin(relations?.inShineConfirmed, targetLogin),
|
inShineConfirmed: listContainsLogin(relations?.inShineConfirmed, targetLogin),
|
||||||
outShineSeen: listContainsLogin(relations?.outShineSeen, targetLogin),
|
outShineSeen: listContainsLogin(relations?.outShineSeen, targetLogin),
|
||||||
|
|||||||
Reference in New Issue
Block a user