for 2.5.1 Merge branch 'master' into develop
This commit is contained in:
commit
69b92f264a
|
@ -1,5 +1,9 @@
|
|||
# Changelog
|
||||
|
||||
### Version 2.5.1
|
||||
* minor bug fixes
|
||||
* Set own OMEMO devices to inactive after not seeing them for 14 days. (was 7 days)
|
||||
|
||||
### Version 2.5.0
|
||||
* Added channel search via search.jabbercat.org
|
||||
* Reworked onboarding screens
|
||||
|
|
|
@ -81,8 +81,8 @@ android {
|
|||
defaultConfig {
|
||||
minSdkVersion 16
|
||||
targetSdkVersion 28
|
||||
versionCode 326
|
||||
versionName "2.5.0"
|
||||
versionCode 327
|
||||
versionName "2.5.1"
|
||||
archivesBaseName += "-$versionName"
|
||||
applicationId "eu.sum7.conversations"
|
||||
resValue "string", "applicationId", applicationId
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="pick_a_server">Hautatu zure XMPP hornitzailea</string>
|
||||
<string name="use_conversations.im">Erabili conversations.im</string>
|
||||
<string name="create_new_account">Kontu berria sortu</string>
|
||||
<string name="do_you_have_an_account">XMPP kontu bat badaukazu dagoeneko? Horrela izan daiteke beste XMPP aplikazio bat erabiltzen baduzu edo Conversations lehenago erabili baduzu. Bestela XMPP kontu berri bat sortu dezakezu oraintxe bertan.\nIradokizuna: email hornitzaile batzuek XMPP kontuak hornitzen dituzte ere.</string>
|
||||
<string name="server_select_text">XMPP hornitzailez independientea den bat-bateko mezularitza sare bat da. Aplikazio hau nahi duzun XMPP zerbitzariarekin erabili dezakezu.\nHala ere zure erosotasunerako conversations.im¹-en, Conversationsekin bereziki erabiltzeko egokia den hornitzaile batean, kontu bat sortzea erraz egin dugu.</string>
|
||||
|
||||
</resources>
|
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="pick_a_server">Escolla o seu provedor XMPP</string>
|
||||
<string name="use_conversations.im">Utilizar conversations.im</string>
|
||||
<string name="create_new_account">Crear nova conta</string>
|
||||
<string name="do_you_have_an_account">Xa posúe unha conta XMPP? Este pode ser o caso se xa está a utilizar outro cliente XMPP ou utilizou Conversations previamente. Se non é así pode crear unha nova conta agora mesmo.\nTruco: Algúns provedores de correo tamén proporcionan contas XMPP.</string>
|
||||
<string name="server_select_text">XMPP é unha rede de mensaxería independente do provedor. Pode utilizar este cliente con calquer provedor XMPP da súa elección.\nMais para a súa conveniencia fixemos que fose doado crear unha conta en conversations.im¹; un provedor especialmente axeitado para utilizar con Conversations.</string>
|
||||
|
||||
</resources>
|
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="pick_a_server">Wybierz dostawcę XMPP</string>
|
||||
<string name="use_conversations.im">Użyj conversations.im</string>
|
||||
<string name="create_new_account">Stwórz nowe konto</string>
|
||||
<string name="do_you_have_an_account">Czy masz już konto XMPP? Tak może być jeśli używasz już innego klienta XMPP lub używałeś już Conversations. Jeśli nie możesz stworzyć nowe konto XMPP teraz.\nPodpowiedź: Niektórzy dostawcy poczty oferują również konta XMPP.</string>
|
||||
<string name="server_select_text">XMPP to niezależna od dostawcy sieć komunikacji błyskawicznej. Możesz użyć tego klienta z dowolnym serwerem XMPP.\nDla twojej wygody jednak ułatwiliśmy stworzenie konta na conversations.im¹; dostawcy specjalnie dostosowanego do pracy z Conversations.</string>
|
||||
|
||||
</resources>
|
|
@ -1,4 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="pick_a_server">Selecione o seu provedor XMPP</string>
|
||||
</resources>
|
||||
<string name="use_conversations.im">Usar o conversations.im</string>
|
||||
<string name="create_new_account">Criar uma nova conta</string>
|
||||
<string name="do_you_have_an_account">Você já possui uma conta XMPP? Esse pode ser o seu caso caso já esteja usando um outro cliente XMPP ou tenha usado o Conversations antes. Caso contrário, você pode criar uma nova conta XMPP agora.\nDica: alguns provedores de e-mail também fornecem contas XMPP.</string>
|
||||
<string name="server_select_text">O XMPP é uma rede de mensageria instantânea independente de provedor. Você pode usar esse cliente com qualquer servidor XMPP que você escolher.\nEntretanto, para sua conveniência, nós simplificamos o processo de criação de uma conta em conversations.im¹, um provedor especialmente configurado para se usar com o Conversations.</string>
|
||||
|
||||
</resources>
|
|
@ -94,7 +94,7 @@ public final class Config {
|
|||
|
||||
public static final long MILLISECONDS_IN_DAY = 24 * 60 * 60 * 1000;
|
||||
|
||||
public static final long OMEMO_AUTO_EXPIRY = 7 * MILLISECONDS_IN_DAY;
|
||||
public static final long OMEMO_AUTO_EXPIRY = 14 * MILLISECONDS_IN_DAY;
|
||||
public static final boolean REMOVE_BROKEN_DEVICES = false;
|
||||
public static final boolean OMEMO_PADDING = false;
|
||||
public static final boolean PUT_AUTH_TAG_INTO_KEY = true;
|
||||
|
@ -122,7 +122,7 @@ public final class Config {
|
|||
|
||||
public static final int EXPIRY_INTERVAL = 30 * 60 * 1000; // 30 minutes
|
||||
|
||||
public static final String ENABLED_CIPHERS[] = {
|
||||
public static final String[] ENABLED_CIPHERS = {
|
||||
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
|
||||
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA384",
|
||||
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA256",
|
||||
|
|
|
@ -3,7 +3,6 @@ package eu.siacs.conversations.entities;
|
|||
import android.content.ContentValues;
|
||||
import android.database.Cursor;
|
||||
import android.graphics.Color;
|
||||
import android.support.annotation.ColorInt;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.util.Log;
|
||||
|
||||
|
@ -181,35 +180,11 @@ public class Message extends AbstractEntity implements AvatarService.Avatarable
|
|||
}
|
||||
|
||||
public static Message fromCursor(Cursor cursor, Conversation conversation) {
|
||||
Jid jid;
|
||||
try {
|
||||
String value = cursor.getString(cursor.getColumnIndex(COUNTERPART));
|
||||
if (value != null) {
|
||||
jid = Jid.of(value);
|
||||
} else {
|
||||
jid = null;
|
||||
}
|
||||
} catch (IllegalArgumentException e) {
|
||||
jid = null;
|
||||
} catch (IllegalStateException e) {
|
||||
return null; // message too long?
|
||||
}
|
||||
Jid trueCounterpart;
|
||||
try {
|
||||
String value = cursor.getString(cursor.getColumnIndex(TRUE_COUNTERPART));
|
||||
if (value != null) {
|
||||
trueCounterpart = Jid.of(value);
|
||||
} else {
|
||||
trueCounterpart = null;
|
||||
}
|
||||
} catch (IllegalArgumentException e) {
|
||||
trueCounterpart = null;
|
||||
}
|
||||
return new Message(conversation,
|
||||
cursor.getString(cursor.getColumnIndex(UUID)),
|
||||
cursor.getString(cursor.getColumnIndex(CONVERSATION)),
|
||||
jid,
|
||||
trueCounterpart,
|
||||
fromString(cursor.getString(cursor.getColumnIndex(COUNTERPART))),
|
||||
fromString(cursor.getString(cursor.getColumnIndex(TRUE_COUNTERPART))),
|
||||
cursor.getString(cursor.getColumnIndex(BODY)),
|
||||
cursor.getLong(cursor.getColumnIndex(TIME_SENT)),
|
||||
cursor.getInt(cursor.getColumnIndex(ENCRYPTION)),
|
||||
|
@ -229,6 +204,17 @@ public class Message extends AbstractEntity implements AvatarService.Avatarable
|
|||
cursor.getInt(cursor.getColumnIndex(DELETED)) > 0);
|
||||
}
|
||||
|
||||
private static Jid fromString(String value) {
|
||||
try {
|
||||
if (value != null) {
|
||||
return Jid.of(value);
|
||||
}
|
||||
} catch (IllegalArgumentException e) {
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Message createStatusMessage(Conversation conversation, String body) {
|
||||
final Message message = new Message(conversation);
|
||||
message.setType(Message.TYPE_STATUS);
|
||||
|
|
|
@ -4,9 +4,11 @@ import com.google.common.base.Objects;
|
|||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import eu.siacs.conversations.services.AvatarService;
|
||||
import eu.siacs.conversations.utils.LanguageUtils;
|
||||
import eu.siacs.conversations.utils.UIHelper;
|
||||
import retrofit2.Call;
|
||||
import retrofit2.http.Body;
|
||||
|
@ -35,6 +37,7 @@ public interface MuclumbusService {
|
|||
public String address;
|
||||
public String name;
|
||||
public String description;
|
||||
public String language;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
|
@ -52,6 +55,10 @@ public interface MuclumbusService {
|
|||
}
|
||||
}
|
||||
|
||||
public String getLanguage() {
|
||||
return LanguageUtils.convert(language);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAvatarBackgroundColor() {
|
||||
Jid room = getRoom();
|
||||
|
|
|
@ -28,10 +28,8 @@ import java.security.cert.CertificateException;
|
|||
import java.security.cert.CertificateFactory;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
@ -750,14 +748,15 @@ public class DatabaseBackend extends SQLiteOpenHelper {
|
|||
null, null, Message.TIME_SENT + " DESC",
|
||||
String.valueOf(limit));
|
||||
}
|
||||
if (cursor.getCount() > 0) {
|
||||
cursor.moveToLast();
|
||||
do {
|
||||
Message message = Message.fromCursor(cursor, conversation);
|
||||
while (cursor.moveToNext()) {
|
||||
try {
|
||||
final Message message = Message.fromCursor(cursor, conversation);
|
||||
if (message != null) {
|
||||
list.add(message);
|
||||
list.add(0, message);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e(Config.LOGTAG,"unable to restore message");
|
||||
}
|
||||
} while (cursor.moveToPrevious());
|
||||
}
|
||||
cursor.close();
|
||||
return list;
|
||||
|
@ -770,40 +769,6 @@ public class DatabaseBackend extends SQLiteOpenHelper {
|
|||
return db.rawQuery(SQL, new String[]{FtsUtils.toMatchString(term)});
|
||||
}
|
||||
|
||||
public Iterable<Message> getMessagesIterable(final Conversation conversation) {
|
||||
return () -> {
|
||||
class MessageIterator implements Iterator<Message> {
|
||||
private SQLiteDatabase db = getReadableDatabase();
|
||||
private String[] selectionArgs = {conversation.getUuid()};
|
||||
private Cursor cursor = db.query(Message.TABLENAME, null, Message.CONVERSATION
|
||||
+ "=?", selectionArgs, null, null, Message.TIME_SENT
|
||||
+ " ASC", null);
|
||||
|
||||
private MessageIterator() {
|
||||
cursor.moveToFirst();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return !cursor.isAfterLast();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Message next() {
|
||||
Message message = Message.fromCursor(cursor, conversation);
|
||||
cursor.moveToNext();
|
||||
return message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
return new MessageIterator();
|
||||
};
|
||||
}
|
||||
|
||||
public List<String> markFileAsDeleted(final File file, final boolean internal) {
|
||||
SQLiteDatabase db = this.getReadableDatabase();
|
||||
String selection;
|
||||
|
|
|
@ -10,6 +10,8 @@ import android.view.LayoutInflater;
|
|||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
import eu.siacs.conversations.R;
|
||||
import eu.siacs.conversations.databinding.SearchResultItemBinding;
|
||||
import eu.siacs.conversations.http.services.MuclumbusService;
|
||||
|
@ -38,7 +40,7 @@ public class ChannelSearchResultAdapter extends ListAdapter<MuclumbusService.Roo
|
|||
@NonNull
|
||||
@Override
|
||||
public ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
|
||||
return new ViewHolder(DataBindingUtil.inflate(LayoutInflater.from(viewGroup.getContext()), R.layout.search_result_item,viewGroup,false));
|
||||
return new ViewHolder(DataBindingUtil.inflate(LayoutInflater.from(viewGroup.getContext()), R.layout.search_result_item, viewGroup, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -46,12 +48,19 @@ public class ChannelSearchResultAdapter extends ListAdapter<MuclumbusService.Roo
|
|||
final MuclumbusService.Room searchResult = getItem(position);
|
||||
viewHolder.binding.name.setText(searchResult.getName());
|
||||
final String description = searchResult.getDescription();
|
||||
final String language = searchResult.getLanguage();
|
||||
if (TextUtils.isEmpty(description)) {
|
||||
viewHolder.binding.description.setVisibility(View.GONE);
|
||||
} else {
|
||||
viewHolder.binding.description.setText(description);
|
||||
viewHolder.binding.description.setVisibility(View.VISIBLE);
|
||||
}
|
||||
if (language == null || language.length() != 2) {
|
||||
viewHolder.binding.language.setVisibility(View.GONE);
|
||||
} else {
|
||||
viewHolder.binding.language.setText(language.toUpperCase(Locale.ENGLISH));
|
||||
viewHolder.binding.language.setVisibility(View.VISIBLE);
|
||||
}
|
||||
viewHolder.binding.room.setText(searchResult.getRoom().asBareJid().toString());
|
||||
AvatarWorkerTask.loadAvatar(searchResult, viewHolder.binding.avatar, R.dimen.avatar);
|
||||
viewHolder.binding.getRoot().setOnClickListener(v -> listener.onChannelSearchResult(searchResult));
|
||||
|
|
|
@ -87,16 +87,20 @@ public class EditMessage extends EmojiWrapperEditText {
|
|||
}
|
||||
|
||||
private void triggerKeyboardEvents(final int length) {
|
||||
final KeyboardListener listener = this.keyboardListener;
|
||||
if (listener == null) {
|
||||
return;
|
||||
}
|
||||
this.mTypingHandler.removeCallbacks(mTypingTimeout);
|
||||
this.mTypingHandler.postDelayed(mTypingTimeout, Config.TYPING_TIMEOUT * 1000);
|
||||
if (!isUserTyping && length > 0) {
|
||||
this.isUserTyping = true;
|
||||
this.keyboardListener.onTypingStarted();
|
||||
listener.onTypingStarted();
|
||||
} else if (length == 0) {
|
||||
this.isUserTyping = false;
|
||||
this.keyboardListener.onTextDeleted();
|
||||
listener.onTextDeleted();
|
||||
}
|
||||
this.keyboardListener.onTextChanged();
|
||||
listener.onTextChanged();
|
||||
}
|
||||
|
||||
public void setKeyboardListener(KeyboardListener listener) {
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
package eu.siacs.conversations.utils;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
public class LanguageUtils {
|
||||
|
||||
private static final Map<String,String> LANGUAGE_MAP;
|
||||
|
||||
static {
|
||||
ImmutableMap.Builder<String, String> builder = new ImmutableMap.Builder<>();
|
||||
builder.put("german","de");
|
||||
builder.put("deutsch","de");
|
||||
builder.put("english","en");
|
||||
builder.put("russian","ru");
|
||||
LANGUAGE_MAP = builder.build();
|
||||
}
|
||||
|
||||
public static String convert(final String in) {
|
||||
if (in == null) {
|
||||
return null;
|
||||
}
|
||||
final String out = LANGUAGE_MAP.get(in.toLowerCase(Locale.US));
|
||||
return out == null ? in : out;
|
||||
}
|
||||
}
|
|
@ -1003,16 +1003,17 @@ public class JingleConnection implements Transferable {
|
|||
}
|
||||
|
||||
private void sendCandidateError() {
|
||||
Log.d(Config.LOGTAG,"sending canditate error");
|
||||
JinglePacket packet = bootstrapPacket("transport-info");
|
||||
Content content = new Content(this.contentCreator, this.contentName);
|
||||
content.setTransportId(this.transportId);
|
||||
content.socks5transport().addChild("candidate-error");
|
||||
packet.setContent(content);
|
||||
this.sentCandidate = true;
|
||||
this.sendJinglePacket(packet);
|
||||
if (receivedCandidate && mJingleStatus == JINGLE_STATUS_ACCEPTED) {
|
||||
connect();
|
||||
}
|
||||
this.sendJinglePacket(packet);
|
||||
}
|
||||
|
||||
public int getJingleStatus() {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
|
@ -14,35 +15,49 @@
|
|||
android:layout_height="48dp"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:scaleType="centerCrop"
|
||||
app:riv_corner_radius="2dp"/>
|
||||
app:riv_corner_radius="2dp" />
|
||||
|
||||
<LinearLayout
|
||||
<RelativeLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_toRightOf="@+id/avatar"
|
||||
android:orientation="vertical"
|
||||
android:layout_marginLeft="@dimen/avatar_item_distance">
|
||||
android:layout_marginLeft="@dimen/avatar_item_distance"
|
||||
android:layout_toRightOf="@+id/avatar">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="@style/TextAppearance.Conversations.Subhead"/>
|
||||
android:textAppearance="@style/TextAppearance.Conversations.Subhead"
|
||||
tools:text="Proosdy IM Chat trantu" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/language"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignBaseline="@id/name"
|
||||
android:layout_marginLeft="8sp"
|
||||
android:layout_toRightOf="@id/name"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="@style/TextAppearance.Conversations.Caption"
|
||||
tools:text="EN" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/description"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/name"
|
||||
android:maxLines="2"
|
||||
android:textAppearance="@style/TextAppearance.Conversations.Body1"/>
|
||||
android:textAppearance="@style/TextAppearance.Conversations.Body1" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/room"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/description"
|
||||
android:maxLines="2"
|
||||
android:textAppearance="@style/TextAppearance.Conversations.Body1.Secondary"/>
|
||||
</LinearLayout>
|
||||
android:textAppearance="@style/TextAppearance.Conversations.Body1.Secondary" />
|
||||
</RelativeLayout>
|
||||
|
||||
</RelativeLayout>
|
||||
</layout>
|
|
@ -422,8 +422,8 @@
|
|||
<string name="no_application_found_to_display_location">Kokapena erakutsi dezakeen aplikaziorik ez da aurkitu</string>
|
||||
<string name="location">Kokapena</string>
|
||||
<string name="title_undo_swipe_out_conversation">Elkarrizketa itxi egin da</string>
|
||||
<string name="title_undo_swipe_out_group_chat">Talde pribatua utzi</string>
|
||||
<string name="title_undo_swipe_out_channel">Kanal publikoa utzi</string>
|
||||
<string name="title_undo_swipe_out_group_chat">Talde pribatua utzi da</string>
|
||||
<string name="title_undo_swipe_out_channel">Kanal publikoa utzi da</string>
|
||||
<string name="pref_dont_trust_system_cas_title">Sistemaren CAtaz ez fidatu</string>
|
||||
<string name="pref_dont_trust_system_cas_summary">Ziurtagiri guztiak eskuz onartu behar dira</string>
|
||||
<string name="pref_remove_trusted_certificates_title">Ziurtagiriak kendu</string>
|
||||
|
@ -850,4 +850,14 @@
|
|||
<string name="search_participants">Parte-hartzaileak bilatu</string>
|
||||
<string name="file_too_large">Fitxategia handiegia da</string>
|
||||
<string name="attach">Erantsi</string>
|
||||
<string name="discover_channels">Kanalak aurkitu</string>
|
||||
<string name="search_channels">Kanalak bilatu</string>
|
||||
<string name="channel_discovery_opt_in_title">Balizko pribatutasun urraketa!</string>
|
||||
<string name="channel_discover_opt_in_message"><![CDATA[Kanalak aurkitzeko ezaugarriak <a href="https://search.jabbercat.org">search.jabbercat.org</a> izeneko hirugarren zerbitzu bat erabiltzen du.<br><br>Ezaugarri hau erabiltzeak zure IP helbidea eta bilatutako testua zerbitzu horretara bidaltzea dakar. Ikusi beren <a href="https://search.jabbercat.org/privacy">pribatutasun politika</a> informazio gehiago lortzeko.]]></string>
|
||||
<string name="i_already_have_an_account">Badaukat kontu bat dagoeneko</string>
|
||||
<string name="add_existing_account">Gehitu existitzen den kontu bat</string>
|
||||
<string name="register_new_account">Kontu berria erregistratu</string>
|
||||
<string name="this_looks_like_a_domain">Honek domeinu helbide baten itxura dauka</string>
|
||||
<string name="add_anway">Gehitu hala ere</string>
|
||||
<string name="this_looks_like_channel">Honek kanal helbide baten itxura dauka</string>
|
||||
</resources>
|
||||
|
|
Loading…
Reference in New Issue