Merge branch 'fastlane'

* fastlane:
  Screenshot add contact options speeddial
  startConversation screenshot
  Draft new full description
  Generate a screenshot with fastlane
This commit is contained in:
Stephen Paul Weber 2022-03-15 09:56:27 -05:00
commit 66731f3f38
No known key found for this signature in database
GPG Key ID: D11C2911CE519CDE
16 changed files with 457 additions and 42 deletions

6
Gemfile Normal file
View File

@ -0,0 +1,6 @@
# frozen_string_literal: true
source "https://rubygems.org"
gem "fastlane"
gem "screengrab"

221
Gemfile.lock Normal file
View File

@ -0,0 +1,221 @@
GEM
remote: https://rubygems.org/
specs:
CFPropertyList (3.0.5)
rexml
addressable (2.8.0)
public_suffix (>= 2.0.2, < 5.0)
artifactory (3.0.15)
atomos (0.1.3)
aws-eventstream (1.2.0)
aws-partitions (1.566.0)
aws-sdk-core (3.130.0)
aws-eventstream (~> 1, >= 1.0.2)
aws-partitions (~> 1, >= 1.525.0)
aws-sigv4 (~> 1.1)
jmespath (~> 1.0)
aws-sdk-kms (1.55.0)
aws-sdk-core (~> 3, >= 3.127.0)
aws-sigv4 (~> 1.1)
aws-sdk-s3 (1.113.0)
aws-sdk-core (~> 3, >= 3.127.0)
aws-sdk-kms (~> 1)
aws-sigv4 (~> 1.4)
aws-sigv4 (1.4.0)
aws-eventstream (~> 1, >= 1.0.2)
babosa (1.0.4)
claide (1.1.0)
colored (1.2)
colored2 (3.1.2)
commander (4.6.0)
highline (~> 2.0.0)
declarative (0.0.20)
digest-crc (0.6.4)
rake (>= 12.0.0, < 14.0.0)
domain_name (0.5.20190701)
unf (>= 0.0.5, < 1.0.0)
dotenv (2.7.6)
emoji_regex (3.2.3)
excon (0.91.0)
faraday (1.10.0)
faraday-em_http (~> 1.0)
faraday-em_synchrony (~> 1.0)
faraday-excon (~> 1.1)
faraday-httpclient (~> 1.0)
faraday-multipart (~> 1.0)
faraday-net_http (~> 1.0)
faraday-net_http_persistent (~> 1.0)
faraday-patron (~> 1.0)
faraday-rack (~> 1.0)
faraday-retry (~> 1.0)
ruby2_keywords (>= 0.0.4)
faraday-cookie_jar (0.0.7)
faraday (>= 0.8.0)
http-cookie (~> 1.0.0)
faraday-em_http (1.0.0)
faraday-em_synchrony (1.0.0)
faraday-excon (1.1.0)
faraday-httpclient (1.0.1)
faraday-multipart (1.0.3)
multipart-post (>= 1.2, < 3)
faraday-net_http (1.0.1)
faraday-net_http_persistent (1.2.0)
faraday-patron (1.0.0)
faraday-rack (1.0.0)
faraday-retry (1.0.3)
faraday_middleware (1.2.0)
faraday (~> 1.0)
fastimage (2.2.6)
fastlane (2.204.3)
CFPropertyList (>= 2.3, < 4.0.0)
addressable (>= 2.8, < 3.0.0)
artifactory (~> 3.0)
aws-sdk-s3 (~> 1.0)
babosa (>= 1.0.3, < 2.0.0)
bundler (>= 1.12.0, < 3.0.0)
colored
commander (~> 4.6)
dotenv (>= 2.1.1, < 3.0.0)
emoji_regex (>= 0.1, < 4.0)
excon (>= 0.71.0, < 1.0.0)
faraday (~> 1.0)
faraday-cookie_jar (~> 0.0.6)
faraday_middleware (~> 1.0)
fastimage (>= 2.1.0, < 3.0.0)
gh_inspector (>= 1.1.2, < 2.0.0)
google-apis-androidpublisher_v3 (~> 0.3)
google-apis-playcustomapp_v1 (~> 0.1)
google-cloud-storage (~> 1.31)
highline (~> 2.0)
json (< 3.0.0)
jwt (>= 2.1.0, < 3)
mini_magick (>= 4.9.4, < 5.0.0)
multipart-post (~> 2.0.0)
naturally (~> 2.2)
optparse (~> 0.1.1)
plist (>= 3.1.0, < 4.0.0)
rubyzip (>= 2.0.0, < 3.0.0)
security (= 0.1.3)
simctl (~> 1.6.3)
terminal-notifier (>= 2.0.0, < 3.0.0)
terminal-table (>= 1.4.5, < 2.0.0)
tty-screen (>= 0.6.3, < 1.0.0)
tty-spinner (>= 0.8.0, < 1.0.0)
word_wrap (~> 1.0.0)
xcodeproj (>= 1.13.0, < 2.0.0)
xcpretty (~> 0.3.0)
xcpretty-travis-formatter (>= 0.0.3)
gh_inspector (1.1.3)
google-apis-androidpublisher_v3 (0.16.0)
google-apis-core (>= 0.4, < 2.a)
google-apis-core (0.4.2)
addressable (~> 2.5, >= 2.5.1)
googleauth (>= 0.16.2, < 2.a)
httpclient (>= 2.8.1, < 3.a)
mini_mime (~> 1.0)
representable (~> 3.0)
retriable (>= 2.0, < 4.a)
rexml
webrick
google-apis-iamcredentials_v1 (0.10.0)
google-apis-core (>= 0.4, < 2.a)
google-apis-playcustomapp_v1 (0.7.0)
google-apis-core (>= 0.4, < 2.a)
google-apis-storage_v1 (0.11.0)
google-apis-core (>= 0.4, < 2.a)
google-cloud-core (1.6.0)
google-cloud-env (~> 1.0)
google-cloud-errors (~> 1.0)
google-cloud-env (1.5.0)
faraday (>= 0.17.3, < 2.0)
google-cloud-errors (1.2.0)
google-cloud-storage (1.36.1)
addressable (~> 2.8)
digest-crc (~> 0.4)
google-apis-iamcredentials_v1 (~> 0.1)
google-apis-storage_v1 (~> 0.1)
google-cloud-core (~> 1.6)
googleauth (>= 0.16.2, < 2.a)
mini_mime (~> 1.0)
googleauth (1.1.2)
faraday (>= 0.17.3, < 3.a)
jwt (>= 1.4, < 3.0)
memoist (~> 0.16)
multi_json (~> 1.11)
os (>= 0.9, < 2.0)
signet (>= 0.16, < 2.a)
highline (2.0.3)
http-cookie (1.0.4)
domain_name (~> 0.5)
httpclient (2.8.3)
jmespath (1.6.1)
json (2.6.1)
jwt (2.3.0)
memoist (0.16.2)
mini_magick (4.11.0)
mini_mime (1.1.2)
multi_json (1.15.0)
multipart-post (2.0.0)
nanaimo (0.3.0)
naturally (2.2.1)
optparse (0.1.1)
os (1.1.4)
plist (3.6.0)
public_suffix (4.0.6)
rake (13.0.6)
representable (3.1.1)
declarative (< 0.1.0)
trailblazer-option (>= 0.1.1, < 0.2.0)
uber (< 0.2.0)
retriable (3.1.2)
rexml (3.2.5)
rouge (2.0.7)
ruby2_keywords (0.0.5)
rubyzip (2.3.2)
screengrab (1.0.0)
fastlane (>= 2.0.0, < 3.0.0)
security (0.1.3)
signet (0.16.1)
addressable (~> 2.8)
faraday (>= 0.17.5, < 3.0)
jwt (>= 1.5, < 3.0)
multi_json (~> 1.10)
simctl (1.6.8)
CFPropertyList
naturally
terminal-notifier (2.0.0)
terminal-table (1.8.0)
unicode-display_width (~> 1.1, >= 1.1.1)
trailblazer-option (0.1.2)
tty-cursor (0.7.1)
tty-screen (0.8.1)
tty-spinner (0.9.3)
tty-cursor (~> 0.7)
uber (0.1.0)
unf (0.1.4)
unf_ext
unf_ext (0.0.8)
unicode-display_width (1.8.0)
webrick (1.7.0)
word_wrap (1.0.0)
xcodeproj (1.21.0)
CFPropertyList (>= 2.3.3, < 4.0)
atomos (~> 0.1.3)
claide (>= 1.0.2, < 2.0)
colored2 (~> 3.1)
nanaimo (~> 0.3.0)
rexml (~> 3.2.4)
xcpretty (0.3.0)
rouge (~> 2.0.7)
xcpretty-travis-formatter (1.0.1)
xcpretty (~> 0.2, >= 0.0.7)
PLATFORMS
x86_64-linux
DEPENDENCIES
fastlane
screengrab
BUNDLED WITH
2.2.5

View File

@ -121,12 +121,12 @@ android {
targetSdkVersion 29
versionCode 42024 + grgit.tag.list().size()
versionName grgit.describe(tags: true, always: true)
archivesBaseName += "-$versionName"
applicationId "eu.siacs.conversations"
resValue "string", "applicationId", applicationId
def appName = "Conversations"
resValue "string", "app_name", appName
buildConfigField "String", "APP_NAME", "\"$appName\"";
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}

2
fastlane/Appfile Normal file
View File

@ -0,0 +1,2 @@
json_key_file("") # Path to the json secret file - Follow https://docs.fastlane.tools/actions/supply/#setup to get one
package_name("com.cheogram.android") # e.g. com.krausefx.app

38
fastlane/Fastfile Normal file
View File

@ -0,0 +1,38 @@
# This file contains the fastlane.tools configuration
# You can find the documentation at https://docs.fastlane.tools
#
# For a list of all available actions, check out
#
# https://docs.fastlane.tools/actions
#
# For a list of all available plugins, check out
#
# https://docs.fastlane.tools/plugins/available-plugins
#
# Uncomment the line if you want fastlane to automatically update itself
# update_fastlane
default_platform(:android)
platform :android do
desc "Build debug and test APK for screenshots"
lane :build_for_screengrab do
build_android_app(
task: 'assemble',
flavor: 'CheogramFree',
build_type: 'Debug'
)
build_android_app(
task: 'assemble',
flavor: 'CheogramFree',
build_type: 'DebugAndroidTest'
)
end
desc "Build and take screenshots"
lane :build_and_screengrab do
build_for_screengrab
capture_android_screenshots
end
end

5
fastlane/Screengrabfile Normal file
View File

@ -0,0 +1,5 @@
locales ['en-US']
clear_previous_screenshots true
tests_apk_path 'build/outputs/apk/androidTest/cheogramFree/debug/Conversations-cheogram-free-debug-androidTest.apk'
app_apk_path 'build/outputs/apk/cheogramFree/debug/Conversations-cheogram-free-debug.apk'
test_instrumentation_runner 'androidx.test.runner.AndroidJUnitRunner'

View File

@ -1,39 +1,16 @@
Easy to use, reliable, battery friendly. With built-in support for images, group chats and e2e encryption.
The Cheogram Android app allows you to join a worldwide communication network. It especially focuses on features useful to users who want to contact those on other networks as well, such as SMS-enabled phone numbers.
Design principles:
Unique Features:
* Be as beautiful and easy to use as possible without sacrificing security or privacy
* Rely on existing, well established protocols
* Do not require a Google Account or specifically Google Cloud Messaging (GCM)
* Require as few permissions as possible
Features:
* End-to-end encryption with either <a href="http://conversations.im/omemo/">OMEMO</a> or <a href="http://openpgp.org/about/">OpenPGP</a>
* Sending and receiving images
* Encrypted audio and video calls (DTLS-SRTP)
* Intuitive UI that follows Android Design guidelines
* Pictures / Avatars for your Contacts
* Syncs with desktop client
* Conferences (with support for bookmarks)
* Messages with both media and text, including animated media
* Unobtrusive display of subject lines, where present
* Links to known contacts are shown with their name
* Integrates with gateways add contact flows
* When using a gateway to the phone network, integrate with the native Android Phone app
* Address book integration
* Multiple accounts / unified inbox
* Very low impact on battery life
Conversations makes it very easy to create an account on the conversations.im server. Using that server comes with an annual fee of 8 Euro after a 6 month trial period. However Conversations will work with any other XMPP server as well. A lot of XMPP servers are run by volunteers and are free of charge.
Where to get service:
XMPP Features:
Cheogram Android requires you have an account with a Jabber service. You can run your own service, or use one provided by someone else, for example: https://snikket.org/hosting/
Conversations works with every XMPP server out there. However XMPP is an extensible protocol. These extensions are standardized as well in so called XEPs. Conversations supports a couple of those to make the overall user experience better. There is a chance that your current XMPP server does not support these extensions. Therefore to get the most out of Conversations you should consider either switching to an XMPP server that does or - even better - run your own XMPP server for you and your friends.
These XEPs are - as of now:
* XEP-0065: SOCKS5 Bytestreams (or mod_proxy65). Will be used to transfer files if both parties are behind a firewall (NAT).
* XEP-0163: Personal Eventing Protocol for avatars
* XEP-0191: Blocking command lets you blacklist spammers or block contacts without removing them from your roster.
* XEP-0198: Stream Management allows XMPP to survive small network outages and changes of the underlying TCP connection.
* XEP-0280: Message Carbons which automatically syncs the messages you send to your desktop client and thus allows you to switch seamlessly from your mobile client to your desktop client and back within one conversation.
* XEP-0237: Roster Versioning mainly to save bandwidth on poor mobile connections
* XEP-0313: Message Archive Management synchronize message history with the server. Catch up with messages that were sent while Conversations was offline.
* XEP-0352: Client State Indication lets the server know whether or not Conversations is in the background. Allows the server to save bandwidth by withholding unimportant packages.
* XEP-0363: HTTP File Upload allows you to share files in conferences and with offline contacts. Requires an additional component on your server.
Art in screenshots is from https://www.peppercarrot.com by David Revoy, CC-BY. Artwork has been modified to crop out sections for avatars and photos, and in some cases add transparency. Use of this artwork does not imply endoresement of this project by the artist.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 653 KiB

After

Width:  |  Height:  |  Size: 654 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 185 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 252 KiB

View File

@ -0,0 +1,169 @@
package com.cheogram.android.test;
import java.util.concurrent.TimeoutException;
import java.lang.Thread;
import java.util.Arrays;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import androidx.test.InstrumentationRegistry;
import androidx.test.core.app.ActivityScenario;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.rules.ActivityScenarioRule;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.rule.ServiceTestRule;
import static androidx.test.espresso.Espresso.onView;
import static androidx.test.espresso.action.ViewActions.click;
import static androidx.test.espresso.matcher.ViewMatchers.withId;
import tools.fastlane.screengrab.Screengrab;
import tools.fastlane.screengrab.cleanstatusbar.CleanStatusBar;
import tools.fastlane.screengrab.locale.LocaleTestRule;
import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.entities.Contact;
import eu.siacs.conversations.entities.Conversation;
import eu.siacs.conversations.entities.Message;
import eu.siacs.conversations.entities.Presence;
import eu.siacs.conversations.entities.ServiceDiscoveryResult;
import eu.siacs.conversations.entities.TransferablePlaceholder;
import eu.siacs.conversations.persistance.FileBackend;
import eu.siacs.conversations.services.XmppConnectionService.XmppConnectionBinder;
import eu.siacs.conversations.services.XmppConnectionService;
import eu.siacs.conversations.test.R;
import eu.siacs.conversations.ui.ConversationsActivity;
import eu.siacs.conversations.ui.StartConversationActivity;
import eu.siacs.conversations.xml.Element;
import eu.siacs.conversations.xmpp.Jid;
import eu.siacs.conversations.xmpp.pep.Avatar;
import eu.siacs.conversations.xmpp.stanzas.IqPacket;
@RunWith(AndroidJUnit4.class)
public class ScreenshotTest {
static String pkg = InstrumentationRegistry.getInstrumentation().getContext().getPackageName();
static XmppConnectionService xmppConnectionService;
static Account account;
@ClassRule
public static final LocaleTestRule localeTestRule = new LocaleTestRule();
@ClassRule
public static final ServiceTestRule xmppServiceRule = new ServiceTestRule();
@BeforeClass
public static void setup() throws TimeoutException {
CleanStatusBar.enableWithDefaults();
Intent intent = new Intent(ApplicationProvider.getApplicationContext(), XmppConnectionService.class);
intent.setAction("ui");
xmppConnectionService = ((XmppConnectionBinder) xmppServiceRule.bindService(intent)).getService();
account = xmppConnectionService.findAccountByJid(Jid.of("carrot@chaosah.hereva"));
if (account == null) {
account = new Account(
Jid.of("carrot@chaosah.hereva"),
"orangeandfurry"
);
xmppConnectionService.createAccount(account);
}
Uri avatarUri = Uri.parse("android.resource://" + pkg + "/" + String.valueOf(R.drawable.carrot));
final Avatar avatar = xmppConnectionService.getFileBackend().getPepAvatar(avatarUri, 192, Bitmap.CompressFormat.WEBP);
xmppConnectionService.getFileBackend().save(avatar);
account.setAvatar(avatar.getFilename());
Contact cheogram = account.getRoster().getContact(Jid.of("cheogram.com"));
cheogram.setOption(Contact.Options.IN_ROSTER);
cheogram.setPhotoUri("android.resource://" + pkg + "/" + String.valueOf(R.drawable.cheogram));
Presence cheogramPresence = Presence.parse(null, null, "");
IqPacket discoPacket = new IqPacket(IqPacket.TYPE.RESULT);
Element query = discoPacket.addChild("query", "http://jabber.org/protocol/disco#info");
Element identity = query.addChild("identity");
identity.setAttribute("category", "gateway");
identity.setAttribute("type", "pstn");
cheogramPresence.setServiceDiscoveryResult(new ServiceDiscoveryResult(discoPacket));
cheogram.updatePresence("gw", cheogramPresence);
}
@AfterClass
public static void teardown() {
CleanStatusBar.disable();
}
@Test
public void testConversation() throws FileBackend.FileCopyException, InterruptedException {
Conversation conversation = xmppConnectionService.findOrCreateConversation(account, Jid.of("+15550737737@cheogram.com"), false, false);
conversation.getContact().setOption(Contact.Options.IN_ROSTER);
conversation.getContact().setSystemName("Pepper");
conversation.getContact().setPhotoUri("android.resource://" + pkg + "/" + String.valueOf(R.drawable.pepper));
Message voicemail = new Message(conversation, "", 0, Message.STATUS_RECEIVED);
voicemail.setOob("https://example.com/thing.mp3");
voicemail.setFileParams(new Message.FileParams("https://example.com/thing.mp3|5000|0|0|10000"));
voicemail.setType(Message.TYPE_FILE);
voicemail.setSubject("Voicemail Recording");
Message transcript = new Message(conversation, "Where are you?", 0, Message.STATUS_RECEIVED);
transcript.setSubject("Voicemail Transcription");
Message picture = new Message(conversation, "", 0, Message.STATUS_SEND_RECEIVED);
picture.setOob("https://example.com/thing.webp");
picture.setType(Message.TYPE_FILE);
xmppConnectionService.getFileBackend().copyFileToPrivateStorage(
picture,
Uri.parse("android.resource://" + pkg + "/" + String.valueOf(R.drawable.komona)),
"image/webp"
);
xmppConnectionService.getFileBackend().updateFileParams(picture);
conversation.addAll(0, Arrays.asList(
voicemail,
transcript,
new Message(conversation, "Meow", 0, Message.STATUS_SEND_RECEIVED),
picture,
new Message(conversation, "👍", 0, Message.STATUS_RECEIVED)
));
ActivityScenario scenario = ActivityScenario.launch(ConversationsActivity.class);
scenario.onActivity((Activity activity) -> {
((ConversationsActivity) activity).switchToConversation(conversation);
});
InstrumentationRegistry.getInstrumentation().waitForIdleSync();
Thread.sleep(100); // ImageView not paited yet after waitForIdleSync
Screengrab.screenshot("conversation");
}
@Test
public void testStartConversation() throws InterruptedException {
ActivityScenario scenario = ActivityScenario.launch(StartConversationActivity.class);
InstrumentationRegistry.getInstrumentation().waitForIdleSync();
Thread.sleep(100); // ImageView not paited yet after waitForIdleSync
Screengrab.screenshot("startConversation");
}
@Test
public void testAddContact() throws InterruptedException {
ActivityScenario scenario = ActivityScenario.launch(StartConversationActivity.class);
onView(withId(eu.siacs.conversations.R.id.speed_dial)).perform(click());
Screengrab.screenshot("startConversationOptions");
// Not actually online, so can't screenshot the gateway selector yet
/*onView(withId(eu.siacs.conversations.R.id.create_contact)).perform(click());
InstrumentationRegistry.getInstrumentation().waitForIdleSync();
Thread.sleep(10000); // ImageView not paited yet after waitForIdleSync
Screengrab.screenshot("addContact");*/
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

View File

@ -528,15 +528,12 @@ public final class MimeUtils {
public static String guessMimeTypeFromUriAndMime(final Context context, final Uri uri, final String mime) {
Log.d(Config.LOGTAG, "guessMimeTypeFromUriAndMime " + uri + " and mime=" + mime);
if (mime == null || mime.equals("application/octet-stream")) {
final String guess = guessMimeTypeFromUri(context, uri);
if (guess != null) {
return guess;
} else {
return mime;
}
final String guess = guessMimeTypeFromUri(context, uri);
if (guess != null) {
return guess;
} else {
return mime;
}
return guessMimeTypeFromUri(context, uri);
}
public static String guessMimeTypeFromUri(Context context, Uri uri) {