Initial push

Signed-off-by: Joey Rizzoli <joey@lineageos.org>
gugelfrei
Joey Rizzoli 7 years ago
parent c11c303e26
commit 60de8781c2

3
.gitignore vendored

@ -1,8 +1,7 @@
*.iml
.gradle
/local.properties
/.idea/workspace.xml
/.idea/libraries
/.idea
.DS_Store
/build
/captures

1
app/.gitignore vendored

@ -0,0 +1 @@
/build

@ -0,0 +1,36 @@
apply plugin: 'com.android.application'
android {
compileSdkVersion 25
buildToolsVersion "25.0.2"
defaultConfig {
applicationId "org.lineageos.jelly"
minSdkVersion 23
targetSdkVersion 25
versionCode 1
versionName "1.0"
jackOptions.enabled true
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
lintOptions {
disable 'RestrictedApi'
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:25.3.1'
compile 'com.android.support:design:25.3.1'
compile 'com.android.support:cardview-v7:25.3.1'
compile 'com.android.support:palette-v7:25.3.1'
compile 'com.android.support:support-v4:25.3.1'
}

@ -0,0 +1,25 @@
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in /home/joey/android/android-sdk/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
-keepclassmembers class fqcn.of.javascript.interface.for.webview {
public *;
}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile

@ -0,0 +1,95 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2017 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.lineageos.jelly">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT" />
<application
android:allowBackup="true"
android:fullBackupContent="@xml/backup_descriptor"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name="org.lineageos.jelly.MainActivity"
android:documentLaunchMode="always"
android:hardwareAccelerated="true"
android:label="@string/app_name"
android:persistent="true"
android:theme="@style/AppTheme.NoActionBar"
android:windowSoftInputMode="stateHidden">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="http" />
<data android:scheme="https" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="http" />
<data android:scheme="https" />
<data android:mimeType="text/html" />
<data android:mimeType="text/plain" />
<data android:mimeType="application/xhtml+xml" />
<data android:mimeType="application/vnd.wap.xhtml+xml" />
</intent-filter>
</activity>
<activity
android:name="org.lineageos.jelly.history.HistoryActivity"
android:label="@string/history_title"
android:theme="@style/AppTheme.NoActionBar" />
<activity
android:name="org.lineageos.jelly.favorite.FavoriteActivity"
android:label="@string/favorite_title"
android:theme="@style/AppTheme.NoActionBar" />
<activity
android:name="org.lineageos.jelly.SettingsActivity"
android:label="@string/settings_title"
android:theme="@style/AppTheme.NoActionBar" />
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="org.lineageos.jelly.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_provider" />
</provider>
</application>
</manifest>

@ -0,0 +1,395 @@
/*
* Copyright (C) 2017 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.lineageos.jelly;
import android.Manifest;
import android.annotation.SuppressLint;
import android.app.ActivityManager;
import android.app.DownloadManager;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.ColorDrawable;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.preference.PreferenceManager;
import android.support.annotation.NonNull;
import android.support.design.widget.BottomSheetDialog;
import android.support.design.widget.CoordinatorLayout;
import android.support.design.widget.Snackbar;
import android.support.v4.content.ContextCompat;
import android.support.v4.content.FileProvider;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.view.menu.MenuBuilder;
import android.support.v7.view.menu.MenuPopupHelper;
import android.support.v7.widget.PopupMenu;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.ContextThemeWrapper;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.View;
import android.view.WindowManager;
import android.webkit.CookieManager;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ProgressBar;
import org.lineageos.jelly.favorite.Favorite;
import org.lineageos.jelly.favorite.FavoriteActivity;
import org.lineageos.jelly.favorite.FavoriteDatabaseHandler;
import org.lineageos.jelly.history.HistoryActivity;
import org.lineageos.jelly.utils.PrefsUtils;
import org.lineageos.jelly.utils.UiUtils;
import org.lineageos.jelly.webview.WebViewExt;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
public class MainActivity extends AppCompatActivity {
public static final int FILE_CHOOSER_REQ = 421;
private static final String TAG = MainActivity.class.getSimpleName();
private static final String PROVIDER = "org.lineageos.jelly.fileprovider";
private static final String EXTRA_INCOGNITO = "extra_incognito";
private static final int STORAGE_PERM_REQ = 423;
private static final int LOCATION_PERM_REQ = 424;
private CoordinatorLayout mCoordinator;
private WebViewExt mWebView;
private Bitmap mUrlIcon;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
mCoordinator = (CoordinatorLayout) findViewById(R.id.coordinator_layout);
SwipeRefreshLayout refreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipe_refresh);
refreshLayout.setOnRefreshListener(() -> {
mWebView.reload();
new Handler().postDelayed(() -> refreshLayout.setRefreshing(false), 1000);
});
ProgressBar progressBar = (ProgressBar) findViewById(R.id.load_progress);
EditText editText = (EditText) findViewById(R.id.url_bar);
editText.setOnKeyListener((v, keyCode, event) -> {
if (event.getAction() != KeyEvent.ACTION_DOWN) {
return true;
}
switch (keyCode) {
case KeyEvent.KEYCODE_ENTER:
case KeyEvent.KEYCODE_DPAD_CENTER:
case KeyEvent.KEYCODE_NUMPAD_ENTER:
mWebView.loadUrl(editText.getText().toString());
break;
}
return true;
});
Intent intent = getIntent();
String url = intent.getDataString();
boolean incognito = intent.getBooleanExtra(EXTRA_INCOGNITO, false);
// Make sure prefs are set before loading them
PreferenceManager.setDefaultValues(this, R.xml.settings, false);
setupMenu();
mWebView = (WebViewExt) findViewById(R.id.web_view);
mWebView.init(this, editText, progressBar, incognito);
mWebView.loadUrl(url == null ? PrefsUtils.getHomePage(this) : url);
}
@Override
protected void onResume() {
CookieManager.setAcceptFileSchemeCookies(PrefsUtils.getCookie(this));
super.onResume();
if (PrefsUtils.getLookLock(this)) {
getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE,
WindowManager.LayoutParams.FLAG_SECURE);
} else {
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_SECURE);
}
}
@Override
public void onBackPressed() {
if (mWebView.canGoBack()) {
mWebView.goBack();
} else {
super.onBackPressed();
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] results) {
switch (requestCode) {
case LOCATION_PERM_REQ:
if (hasLocationPermission()) {
mWebView.reload();
}
break;
case STORAGE_PERM_REQ:
if (hasStoragePermission()) {
if (shouldShowRequestPermissionRationale(
Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
new AlertDialog.Builder(this)
.setTitle(R.string.permission_error_title)
.setMessage(R.string.permission_error_storage)
.setCancelable(false)
.setPositiveButton(getString(R.string.permission_error_ask_again),
((dialog, which) -> requestStoragePermission()))
.setNegativeButton(getString(R.string.dismiss),
(((dialog, which) -> dialog.dismiss())))
.show();
} else {
Snackbar.make(mCoordinator, getString(R.string.permission_error_forever),
Snackbar.LENGTH_LONG).show();
}
}
break;
}
}
private void setupMenu() {
ImageButton menu = (ImageButton) findViewById(R.id.search_menu);
menu.setOnClickListener(v -> {
ContextThemeWrapper wrapper = new ContextThemeWrapper(this,
R.style.AppTheme_PopupMenuOverlapAnchor);
PopupMenu popupMenu = new PopupMenu(wrapper, menu, Gravity.NO_GRAVITY,
R.attr.actionOverflowMenuStyle, 0);
popupMenu.inflate(R.menu.menu_main);
popupMenu.setOnMenuItemClickListener(item -> {
switch (item.getItemId()) {
case R.id.menu_new:
openInNewTab(null);
break;
case R.id.menu_incognito:
Intent intent = new Intent(this, MainActivity.class);
intent.putExtra(EXTRA_INCOGNITO, true);
startActivity(intent);
break;
case R.id.menu_reload:
mWebView.reload();
break;
case R.id.menu_add_favorite:
setAsFavorite(mWebView.getTitle(), mWebView.getUrl());
break;
case R.id.menu_share:
// Delay a bit to allow popup menu hide animation to play
new Handler().postDelayed(() -> shareUrl(mWebView.getUrl()), 300);
break;
case R.id.menu_favorite:
startActivity(new Intent(this, FavoriteActivity.class));
break;
case R.id.menu_history:
startActivity(new Intent(this, HistoryActivity.class));
break;
case R.id.menu_shortcut:
addShortcut();
break;
case R.id.menu_settings:
startActivity(new Intent(this, SettingsActivity.class));
break;
}
return true;
});
// Fuck you, lint
//noinspection RestrictedApi
MenuPopupHelper helper = new MenuPopupHelper(wrapper,
(MenuBuilder) popupMenu.getMenu(), menu);
//noinspection RestrictedApi
helper.setForceShowIcon(true);
//noinspection RestrictedApi
helper.show();
});
}
private void openInNewTab(String url) {
Intent intent = new Intent(this, MainActivity.class);
intent.setData(Uri.parse(url));
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT | Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
startActivity(intent);
}
private void shareUrl(String url) {
Intent intent = new Intent(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_TEXT, url);
if (PrefsUtils.getAdvancedShare(this) && url.equals(mWebView.getUrl())) {
try {
File file = new File(getCacheDir(),
String.valueOf(System.currentTimeMillis()) + ".png");
FileOutputStream out = new FileOutputStream(file);
Bitmap bm = mWebView.getSnap();
if (bm == null) {
return;
}
bm.compress(Bitmap.CompressFormat.PNG, 70, out);
out.flush();
out.close();
intent.putExtra(Intent.EXTRA_STREAM,
FileProvider.getUriForFile(this, PROVIDER, file));
intent.setType("image/png");
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
} catch (IOException e) {
Log.e(TAG, e.getMessage());
}
} else {
intent.setType("text/plain");
}
startActivity(intent);
}
private void setAsFavorite(String title, String url) {
FavoriteDatabaseHandler handler = new FavoriteDatabaseHandler(this);
boolean hasValidIcon = mUrlIcon != null && !mUrlIcon.isRecycled();
handler.addItem(new Favorite(title, url, hasValidIcon ?
UiUtils.getColor(this, mUrlIcon, false) :
ContextCompat.getColor(this, R.color.colorAccent)));
Snackbar.make(mCoordinator, getString(R.string.favorite_added),
Snackbar.LENGTH_LONG).show();
}
public void downloadFileAsk(String url, String fileName) {
if (!hasStoragePermission()) {
requestStoragePermission();
return;
}
new AlertDialog.Builder(this)
.setTitle(R.string.download_title)
.setMessage(getString(R.string.download_message, fileName))
.setPositiveButton(getString(R.string.download_positive),
(dialog, which) -> fetchFile(url, fileName))
.setNegativeButton(getString(R.string.dismiss),
((dialog, which) -> dialog.dismiss()))
.show();
}
private void fetchFile(String url, String fileName) {
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE);
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, fileName);
DownloadManager manager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
manager.enqueue(request);
}
public void showSheetMenu(String url, boolean shouldAllowDownload) {
final BottomSheetDialog sheet = new BottomSheetDialog(this);
@SuppressLint("InflateParams")
View view = getLayoutInflater().inflate(R.layout.sheet_actions, null);
View tabLayout = view.findViewById(R.id.sheet_new_tab);
View shareLayout = view.findViewById(R.id.sheet_share);
View favouriteLayout = view.findViewById(R.id.sheet_favourite);
View downloadLayout = view.findViewById(R.id.sheet_download);
tabLayout.setOnClickListener(v -> openInNewTab(url));
shareLayout.setOnClickListener(v -> shareUrl(url));
favouriteLayout.setOnClickListener(v -> setAsFavorite(url, url));
if (shouldAllowDownload) {
downloadLayout.setOnClickListener(v -> downloadFileAsk(url, ""));
downloadLayout.setVisibility(View.VISIBLE);
}
sheet.setContentView(view);
sheet.show();
}
private void requestStoragePermission() {
String[] permissionArray = new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE};
requestPermissions(permissionArray, STORAGE_PERM_REQ);
}
private boolean hasStoragePermission() {
int result = checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE);
return result == PackageManager.PERMISSION_GRANTED;
}
public void requestLocationPermission() {
String[] permissionArray = new String[]{Manifest.permission.ACCESS_FINE_LOCATION};
requestPermissions(permissionArray, LOCATION_PERM_REQ);
}
public boolean hasLocationPermission() {
int result = checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION);
return result == PackageManager.PERMISSION_GRANTED;
}
public void setColor(Bitmap favicon, boolean incognito) {
ActionBar actionBar = getSupportActionBar();
if (favicon == null || favicon.isRecycled() || actionBar == null) {
return;
}
mUrlIcon = favicon.copy(favicon.getConfig(), true);
int color = UiUtils.getColor(this, favicon, incognito);
actionBar.setBackgroundDrawable(new ColorDrawable(color));
getWindow().setStatusBarColor(color);
int flags = getWindow().getDecorView().getSystemUiVisibility();
if (UiUtils.isColorLight(color)) {
flags |= View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
} else {
flags &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
}
getWindow().getDecorView().setSystemUiVisibility(flags);
setTaskDescription(new ActivityManager.TaskDescription(mWebView.getTitle(),
favicon, color));
if (!favicon.isRecycled()) {
favicon.recycle();
}
}
private void addShortcut() {
Intent intent = new Intent(this, MainActivity.class);
intent.setData(Uri.parse(mWebView.getUrl()));
intent.setAction(Intent.ACTION_MAIN);
Bitmap icon = mUrlIcon == null ?
BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher) : mUrlIcon;
Bitmap launcherIcon = UiUtils.getShortcutIcon(this, icon);
Intent addIntent = new Intent();
addIntent.putExtra(Intent.EXTRA_SHORTCUT_NAME, mWebView.getTitle());
addIntent.putExtra(Intent.EXTRA_SHORTCUT_ICON, launcherIcon);
addIntent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, intent);
addIntent.setAction("com.android.launcher.action.INSTALL_SHORTCUT");
sendBroadcast(addIntent);
launcherIcon.recycle();
Snackbar.make(mCoordinator, getString(R.string.shortcut_added),
Snackbar.LENGTH_LONG).show();
}
}

@ -0,0 +1,66 @@
/*
* Copyright (C) 2017 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.lineageos.jelly;
import android.os.Bundle;
import android.preference.Preference;
import android.preference.PreferenceFragment;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
// "noSuchMethodError" is thrown if lambda is used in this class (wtf)
@SuppressWarnings("Convert2Lambda")
public class SettingsActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_settings);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
toolbar.setNavigationIcon(R.drawable.ic_back);
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
}
public static class MyPreferenceFragment extends PreferenceFragment {
@Override
public void onCreate(Bundle savedInstance) {
super.onCreate(savedInstance);
addPreferencesFromResource(R.xml.settings);
Preference homePage = findPreference("key_home_page");
homePage.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
homePage.setSummary(newValue.toString());
return true;
}
});
if (homePage.getSummary() == null) {
homePage.setSummary(getString(R.string.default_home_page));
}
}
}
}

@ -0,0 +1,64 @@
/*
* Copyright (C) 2017 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.lineageos.jelly.favorite;
public class Favorite {
private long id = -1;
private String title;
private String url;
private int color;
public Favorite(String title, String url, int color) {
this.title = title;
this.url = url;
this.color = color;
}
Favorite(long id, String title, String url, int color) {
this.id = id;
this.title = title;
this.url = url;
this.color = color;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
String getUrl() {
return url;
}
void setUrl(String url) {
this.url = url;
}
public int getColor() {
return color;
}
}

@ -0,0 +1,155 @@
/*
* Copyright (C) 2017 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.lineageos.jelly.favorite;
import android.annotation.SuppressLint;
import android.os.Bundle;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.EditText;
import org.lineageos.jelly.R;
import org.lineageos.jelly.utils.UiUtils;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class FavoriteActivity extends AppCompatActivity {
private RecyclerView mList;
private View mEmptyView;
private FavoriteDatabaseHandler mDbHandler;
private FavoriteAdapter mAdapter;
@Override
protected void onCreate(Bundle savedInstance) {
super.onCreate(savedInstance);
setContentView(R.layout.activity_favorites);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
toolbar.setNavigationIcon(R.drawable.ic_back);
toolbar.setNavigationOnClickListener(v -> finish());
mList = (RecyclerView) findViewById(R.id.favorite_list);
mEmptyView = findViewById(R.id.favorite_empty_layout);
mDbHandler = new FavoriteDatabaseHandler(this);
mAdapter = new FavoriteAdapter(this, new ArrayList<>());
mList.setLayoutManager(new GridLayoutManager(this, 2));
mList.setItemAnimator(new DefaultItemAnimator());
mList.setAdapter(mAdapter);
int listTop = mList.getTop();
mList.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
toolbar.setElevation(recyclerView.getChildAt(0).getTop() < listTop ?
UiUtils.dpToPx(getResources(), 8) : 0);
}
});
}
@Override
public void onResume() {
super.onResume();
refresh();
}
void refresh() {
List<Favorite> items = mDbHandler.getAllItems();
// Reverse database list order
Collections.reverse(items);
mAdapter.updateList(items);
if (items.isEmpty()) {
mList.setVisibility(View.GONE);
mEmptyView.setVisibility(View.VISIBLE);
}
}
boolean editItem(Favorite item) {
@SuppressLint("InflateParams")
View view = LayoutInflater.from(this).inflate(R.layout.dialog_favorite_edit, null);
EditText titleEdit = (EditText) view.findViewById(R.id.favorite_edit_title);
EditText urlEdit = (EditText) view.findViewById(R.id.favorite_edit_url);
titleEdit.setText(item.getTitle());
urlEdit.setText(item.getUrl());
String error = getString(R.string.favorite_edit_error);
urlEdit.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if (!s.toString().contains("http")) {
urlEdit.setError(error);
}
}
@Override
public void afterTextChanged(Editable s) {
if (!s.toString().contains("http")) {
urlEdit.setError(error);
}
}
});
new AlertDialog.Builder(this)
.setTitle(R.string.favorite_edit_dialog_title)
.setView(view)
.setPositiveButton(R.string.favorite_edit_positive,
((dialog, which) -> {
String url = urlEdit.getText().toString();
String title = titleEdit.getText().toString();
if (url.isEmpty()) {
urlEdit.setError(error);
urlEdit.requestFocus();
}
item.setTitle(title);
item.setUrl(url);
mDbHandler.updateItem(item);
refresh();
dialog.dismiss();
}))
.setNeutralButton(R.string.favorite_edit_delete,
(dialog, which) -> {
mDbHandler.deleteItem(item.getId());
mAdapter.removeItem(item.getId());
dialog.dismiss();
})
.setNegativeButton(android.R.string.cancel,
(dialog, which) -> dialog.dismiss())
.show();
return true;
}
}

@ -0,0 +1,77 @@
/*
* Copyright (C) 2017 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.lineageos.jelly.favorite;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.ViewGroup;
import org.lineageos.jelly.R;
import java.util.List;
class FavoriteAdapter extends RecyclerView.Adapter<FavoriteHolder> {
private final Context mContext;
private List<Favorite> mList;
FavoriteAdapter(Context context, List<Favorite> list) {
mContext = context;
mList = list;
}
@Override
public FavoriteHolder onCreateViewHolder(ViewGroup parent, int type) {
return new FavoriteHolder(LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_favorite, parent, false));
}
@Override
public void onBindViewHolder(FavoriteHolder holder, int position) {
holder.setData(mContext, mList.get(position));
}
@Override
public int getItemCount() {
return mList.size();
}
void updateList(List<Favorite> list) {
mList = list;
notifyDataSetChanged();
}
void removeItem(long id) {
int position = 0;
for (; position < mList.size(); position++) {
if (mList.get(position).getId() == id) {
break;
}
}
if (position == mList.size()) {
return;
}
mList.remove(position);
notifyItemRemoved(position);
if (mList.isEmpty()) {
// Show empty status
((FavoriteActivity) mContext).refresh();
}
}
}

@ -0,0 +1,105 @@
/*
* Copyright (C) 2017 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.lineageos.jelly.favorite;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import java.util.ArrayList;
import java.util.List;
public class FavoriteDatabaseHandler extends SQLiteOpenHelper {
private static final int DB_VERSION = 1;
private static final String DB_NAME = "FavoriteDatabase";
private static final String DB_TABLE_FAVORITES = "favorites";
private static final String KEY_ID = "id";
private static final String KEY_TITLE = "title";
private static final String KEY_URL = "url";
private static final String KEY_COLOR = "color";
public FavoriteDatabaseHandler(Context context) {
super(context, DB_NAME, null, DB_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE " + DB_TABLE_FAVORITES + " (" +
KEY_ID + " INTEGER PRIMARY KEY, " +
KEY_TITLE + " TEXT, " +
KEY_URL + " TEXT, " +
KEY_COLOR + " INTEGER)");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// Update this when db table will be changed
}
public void addItem(Favorite item) {
if (item.getId() == -1) {
item.setId(System.currentTimeMillis());
}
ContentValues values = new ContentValues();
values.put(KEY_ID, item.getId());
values.put(KEY_TITLE, item.getTitle());
values.put(KEY_URL, item.getUrl());
values.put(KEY_COLOR, item.getColor());
SQLiteDatabase db = getWritableDatabase();
db.insert(DB_TABLE_FAVORITES, null, values);
db.close();
}
void updateItem(Favorite item) {
SQLiteDatabase db = getWritableDatabase();
ContentValues values = new ContentValues();
values.put(KEY_TITLE, item.getTitle());
values.put(KEY_URL, item.getUrl());
values.put(KEY_COLOR, item.getColor());
db.update(DB_TABLE_FAVORITES, values, KEY_ID + "=?",
new String[]{String.valueOf(item.getId())});
}
void deleteItem(long id) {
SQLiteDatabase db = getWritableDatabase();
db.delete(DB_TABLE_FAVORITES, KEY_ID + "=?", new String[]{String.valueOf(id)});
db.close();
}
List<Favorite> getAllItems() {
List<Favorite> list = new ArrayList<>();
SQLiteDatabase db = getWritableDatabase();
Cursor cursor = db.rawQuery("SELECT * FROM " + DB_TABLE_FAVORITES, null);
if (cursor.moveToFirst()) {
do {
list.add(new Favorite(Long.parseLong(cursor.getString(0)),
cursor.getString(1), cursor.getString(2),
Integer.parseInt(cursor.getString(3))));
} while (cursor.moveToNext());
}
cursor.close();
db.close();
return list;
}
}

@ -0,0 +1,58 @@
/*
* Copyright (C) 2017 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.lineageos.jelly.favorite;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.net.Uri;
import android.support.v7.widget.CardView;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.TextView;
import org.lineageos.jelly.MainActivity;
import org.lineageos.jelly.R;
import org.lineageos.jelly.utils.UiUtils;
class FavoriteHolder extends RecyclerView.ViewHolder {
private final CardView mCard;
private final TextView mTitle;
FavoriteHolder(View view) {
super(view);
mCard = (CardView) view.findViewById(R.id.row_favorite_card);
mTitle = (TextView) view.findViewById(R.id.row_favorite_title);
}
void setData(Context context, Favorite item) {
String title = item.getTitle();
if (title == null || title.isEmpty()) {
title = item.getUrl().split("/")[2];
}
mTitle.setText(title);
mTitle.setTextColor(UiUtils.isColorLight(item.getColor()) ? Color.BLACK : Color.WHITE);
mCard.setCardBackgroundColor(item.getColor());
mCard.setOnClickListener(v -> {
Intent intent = new Intent(context, MainActivity.class);
intent.setData(Uri.parse(item.getUrl()));
context.startActivity(intent);
});
mCard.setOnLongClickListener(v -> ((FavoriteActivity) context).editItem(item));
}
}

@ -0,0 +1,146 @@
/*
* Copyright (C) 2017 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.lineageos.jelly.history;
import android.app.ProgressDialog;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import org.lineageos.jelly.R;
import org.lineageos.jelly.utils.UiUtils;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class HistoryActivity extends AppCompatActivity {
private RecyclerView mList;
private View mEmptyView;
private HistoryDatabaseHandler mDbHandler;
private HistoryAdapter mAdapter;
@Override
protected void onCreate(Bundle savedInstance) {
super.onCreate(savedInstance);
setContentView(R.layout.activity_history);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
toolbar.setNavigationIcon(R.drawable.ic_back);
toolbar.setNavigationOnClickListener(v -> finish());
mList = (RecyclerView) findViewById(R.id.history_list);
mEmptyView = findViewById(R.id.history_empty_layout);
mDbHandler = new HistoryDatabaseHandler(this);
mAdapter = new HistoryAdapter(this, new ArrayList<>());
mList.setLayoutManager(new LinearLayoutManager(this));
mList.setItemAnimator(new DefaultItemAnimator());
mList.setAdapter(mAdapter);
int listTop = mList.getTop();
mList.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
toolbar.setElevation(recyclerView.getChildAt(0).getTop() < listTop ?
UiUtils.dpToPx(getResources(), 8) : 0);
}
});
}
@Override
public void onResume() {
super.onResume();
refresh();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_history, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() != R.id.menu_history_delete) {
return super.onOptionsItemSelected(item);
}
new AlertDialog.Builder(this)
.setTitle(R.string.history_delete_title)
.setMessage(R.string.history_delete_message)
.setPositiveButton(R.string.history_delete_positive,
(dialog, which) -> deleteAll())
.setNegativeButton(android.R.string.cancel, (d, w) -> d.dismiss())
.show();
return true;
}
void refresh() {
List<HistoryItem> items = mDbHandler.getAllItems();
// Reverse database list order
Collections.reverse(items);
mAdapter.updateList(items);
if (items.isEmpty()) {
mList.setVisibility(View.GONE);
mEmptyView.setVisibility(View.VISIBLE);
}
}
private void deleteAll() {
ProgressDialog dialog = new ProgressDialog(this);
dialog.setTitle(getString(R.string.history_delete_title));
dialog.setMessage(getString(R.string.history_deleting_message));
dialog.setCancelable(false);
dialog.setIndeterminate(true);
dialog.show();
new AsyncTask<Void, Void, Boolean>() {
@Override
protected Boolean doInBackground(Void... params) {
mDbHandler.deleteAll();
return true;
}
@Override
protected void onPostExecute(Boolean param) {
new Handler().postDelayed(() -> {
dialog.dismiss();
refresh();
}, 1000);
}
}.execute();
}
HistoryAdapter getAdapter() {
return mAdapter;
}
}

@ -0,0 +1,78 @@
/*
* Copyright (C) 2017 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.lineageos.jelly.history;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.ViewGroup;
import org.lineageos.jelly.R;
import java.util.List;
class HistoryAdapter extends RecyclerView.Adapter<HistoryHolder> {
private final Context mContext;
private List<HistoryItem> mList;
HistoryAdapter(Context context, List<HistoryItem> list) {
mContext = context;
mList = list;
}
@Override
public HistoryHolder onCreateViewHolder(ViewGroup parent, int type) {
return new HistoryHolder(LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_history, parent, false));
}
@Override
public void onBindViewHolder(HistoryHolder holder, int position) {
holder.setData(mContext, mList.get(position));
}
@Override
public int getItemCount() {
return mList.size();
}
void updateList(List<HistoryItem> list) {
mList = list;
notifyDataSetChanged();
}
void removeItem(long id) {
int position = 0;
for (; position < mList.size(); position++) {
if (mList.get(position).getId() == id) {
break;
}
}
if (position == mList.size()) {
return;
}
mList.remove(position);
notifyItemRemoved(position);
if (mList.isEmpty()) {
// Show empty status
((HistoryActivity) mContext).refresh();
}
}
}

@ -0,0 +1,96 @@
/*
* Copyright (C) 2017 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.lineageos.jelly.history;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import java.util.ArrayList;
import java.util.List;
public class HistoryDatabaseHandler extends SQLiteOpenHelper {
private static final int DB_VERSION = 1;
private static final String DB_NAME = "HistoryDatabase";
private static final String DB_TABLE_HISTORY = "history";
private static final String KEY_ID = "id";
private static final String KEY_TITLE = "title";
private static final String KEY_URL = "url";
public HistoryDatabaseHandler(Context context) {
super(context, DB_NAME, null, DB_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE " + DB_TABLE_HISTORY + " (" +
KEY_ID + " INTEGER PRIMARY KEY, " +
KEY_TITLE + " TEXT, " +
KEY_URL + " TEXT)");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// Update this when db table will be changed
}
public void addItem(HistoryItem item) {
if (item.getId() == -1) {
item.setId(System.currentTimeMillis());
}
ContentValues values = new ContentValues();
values.put(KEY_ID, item.getId());
values.put(KEY_TITLE, item.getTitle());
values.put(KEY_URL, item.getUrl());
SQLiteDatabase db = getWritableDatabase();
db.insert(DB_TABLE_HISTORY, null, values);
db.close();
}
void deleteItem(long id) {
SQLiteDatabase db = getWritableDatabase();
db.delete(DB_TABLE_HISTORY, KEY_ID + "=?", new String[]{String.valueOf(id)});
db.close();
}
List<HistoryItem> getAllItems() {
List<HistoryItem> list = new ArrayList<>();
SQLiteDatabase db = getWritableDatabase();
Cursor cursor = db.rawQuery("SELECT * FROM " + DB_TABLE_HISTORY, null);
if (cursor.moveToFirst()) {
do {
list.add(new HistoryItem(Long.parseLong(cursor.getString(0)),
cursor.getString(1), cursor.getString(2)));
} while (cursor.moveToNext());
}
cursor.close();
db.close();
return list;
}
void deleteAll() {
SQLiteDatabase db = getWritableDatabase();
db.delete(DB_TABLE_HISTORY, KEY_ID + ">=?", new String[]{"0"});
db.close();
}
}

@ -0,0 +1,89 @@
/*
* Copyright (C) 2017 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.lineageos.jelly.history;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.support.v4.content.ContextCompat;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
import org.lineageos.jelly.MainActivity;
import org.lineageos.jelly.R;
import org.lineageos.jelly.utils.UiUtils;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
class HistoryHolder extends RecyclerView.ViewHolder {
private final LinearLayout mRootLayout;
private final TextView mTitle;
private final TextView mSummary;
HistoryHolder(View view) {
super(view);
mRootLayout = (LinearLayout) view.findViewById(R.id.row_history_layout);
mTitle = (TextView) view.findViewById(R.id.row_history_title);
mSummary = (TextView) view.findViewById(R.id.row_history_summary);
}
void setData(Context context, HistoryItem item) {
String title = item.getTitle();
if (title == null || title.isEmpty()) {
title = item.getUrl().split("/")[2];
}
mTitle.setText(title);
mSummary.setText(new SimpleDateFormat(context.getString(R.string.history_date_format),
Locale.getDefault()).format(new Date(item.getId())));
mRootLayout.setOnClickListener(v -> {
Intent intent = new Intent(context, MainActivity.class);
intent.setData(Uri.parse(item.getUrl()));
context.startActivity(intent);
});
mRootLayout.setOnLongClickListener(v -> {
new HistoryDatabaseHandler(context).deleteItem(item.getId());
((HistoryActivity) context).getAdapter().removeItem(item.getId());
return true;
});
int background;
switch (UiUtils.getPositionInTime(item.getId())) {
case 0:
background = R.color.history_last_hour;
break;
case 1:
background = R.color.history_today;
break;
case 2:
background = R.color.history_this_week;
break;
case 3:
background = R.color.history_this_month;
break;
default:
background = R.color.history_earlier;
break;
}
mRootLayout.setBackgroundColor(ContextCompat.getColor(context, background));
}
}

@ -0,0 +1,50 @@
/*
* Copyright (C) 2017 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.lineageos.jelly.history;
public class HistoryItem {
private final String title;
private final String url;
private long id = -1;
public HistoryItem(String title, String url) {
this.title = title;
this.url = url;
}
HistoryItem(long id, String title, String url) {
this.id = id;
this.title = title;
this.url = url;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getTitle() {
return title;
}
String getUrl() {
return url;
}
}

@ -0,0 +1,78 @@
/*
* Copyright (C) 2017 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.lineageos.jelly.ui;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Shader;
import android.support.v7.widget.AppCompatEditText;
import android.util.AttributeSet;
public class EditTextExt extends AppCompatEditText {
private int mPositionX;
public EditTextExt(Context context) {
super(context);
}
public EditTextExt(Context context, AttributeSet attrs) {
super(context, attrs);
}
public EditTextExt(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
private static LinearGradient getGradient(float widthEnd, float fadeStart,
float stopStart, float stopEnd, int color) {
return new LinearGradient(0, 0, widthEnd, 0,
new int[] { color, Color.TRANSPARENT, color, color, Color.TRANSPARENT },
new float[] { 0, fadeStart, stopStart, stopEnd, 1f }, Shader.TileMode.CLAMP);
}
@Override
protected void onScrollChanged(int x, int y, int oldX, int oldY) {
super.onScrollChanged(x, y, oldX, oldY);
mPositionX = x;
requestLayout();
}
@Override
public void onDraw(Canvas canvas) {
float lineWidth = getLayout().getLineWidth(0);
float width = getMeasuredWidth();
if (getText() == null || getText().length() == 0 || lineWidth <= width) {
super.onDraw(canvas);
getPaint().setShader(null);
return;
}
int textColor = getCurrentTextColor();
float widthEnd = width + mPositionX;
float percent = (int) (width * 0.2);
float fadeStart = mPositionX / widthEnd;
float stopStart = mPositionX > 0 ? ((mPositionX + percent) / widthEnd) : 0;
float stopEnd = (widthEnd - (lineWidth > widthEnd ? percent : 0)) / widthEnd;
getPaint().setShader(getGradient(widthEnd, fadeStart, stopStart, stopEnd, textColor));
super.onDraw(canvas);
}
}

@ -0,0 +1,71 @@
/*
* Copyright (C) 2017 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.lineageos.jelly.utils;
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import org.lineageos.jelly.R;
public final class PrefsUtils {
private static final String KEY_SEARCH_ENGINE = "key_search_engine";
private static final String KEY_HOME_PAGE = "key_home_page";
private static final String KEY_ADVANCED_SHARE = "key_advanced_share";
private static final String KEY_LOOKLOCK = "key_looklock";
private static final String KEY_JS = "key_javascript";
private static final String KEY_LOCATION = "key_location";
private static final String KEY_COOKIE = "key_cookie";
private PrefsUtils() {
}
public static String getSearchEngine(Context context) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
return prefs.getString(KEY_SEARCH_ENGINE,
context.getString(R.string.default_search_engine));
}
public static String getHomePage(Context context) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
return prefs.getString(KEY_HOME_PAGE, context.getString(R.string.default_home_page));
}
public static boolean getAdvancedShare(Context context) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
return prefs.getBoolean(KEY_ADVANCED_SHARE, false);
}
public static boolean getLookLock(Context context) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
return prefs.getBoolean(KEY_LOOKLOCK, false);
}
public static boolean getJavascript(Context context) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
return prefs.getBoolean(KEY_JS, true);
}
public static boolean getLocation(Context context) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
return prefs.getBoolean(KEY_LOCATION, true);
}
public static boolean getCookie(Context context) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
return prefs.getBoolean(KEY_COOKIE, true);
}
}

@ -0,0 +1,88 @@
/*
* Copyright (C) 2017 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.lineageos.jelly.utils;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.support.v4.content.ContextCompat;
import android.support.v4.graphics.ColorUtils;
import android.support.v7.graphics.Palette;
import android.util.TypedValue;
import org.lineageos.jelly.R;
public final class UiUtils {
private UiUtils() {
}
public static boolean isColorLight(int color) {
int red = Color.red(color);
int green = Color.green(color);
int blue = Color.blue(color);
float hsl[] = new float[3];
ColorUtils.RGBToHSL(red, green, blue, hsl);
return hsl[2] > 0.5f;
}
public static int getColor(Context context, Bitmap bitmap, boolean incognito) {
Palette palette = Palette.from(bitmap).generate();
int primary = ContextCompat.getColor(context, R.color.colorPrimary);
int alternative = ContextCompat.getColor(context, R.color.colorIncognito);
return incognito ?
palette.getMutedColor(alternative) : palette.getVibrantColor(primary);
}
public static Bitmap getShortcutIcon(Context context, Bitmap bitmap) {
Bitmap out = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getWidth(),
Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(out);
int color = getColor(context, bitmap, false);
Paint paint = new Paint();
Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getWidth());
float radius = bitmap.getWidth() / 2;
paint.setAntiAlias(true);
paint.setColor(color);
canvas.drawARGB(0, 0, 0, 0);
canvas.drawCircle(radius, radius, radius, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(bitmap, rect, rect, paint);
return Bitmap.createScaledBitmap(out, 192, 192, true);
}
public static int getPositionInTime(long timeMilliSec) {
long diff = System.currentTimeMillis() - timeMilliSec;
long hour = 1000 * 60 * 60;
long day = hour * 24;
long week = day * 7;
long month = day * 30;
return hour > diff ? 0 : day > diff ? 1 : week > diff ? 2 : month > diff ? 3 : 4;
}
public static float dpToPx(Resources res, int dp) {
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, res.getDisplayMetrics());
}
}

@ -0,0 +1,84 @@
/*
* Copyright (C) 2017 The LineageOS Project
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.lineageos.jelly.utils;
import android.util.Log;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.regex.Pattern;
public final class UrlUtils {
public static final Pattern ACCEPTED_URI_SCHEMA = Pattern.compile(
"(?i)" + // switch on case insensitive matching
"(" + // begin group for schema
"(?:http|https|file|chrome):\\/\\/" +
"|(?:inline|data|about|javascript):" +
")" +
"(.*)"
);
private static final String TAG = UrlUtils.class.getSimpleName();
private UrlUtils() {
}
public static String fixUrl(String inUrl) {
inUrl = inUrl.toLowerCase();
int colon = inUrl.indexOf(':');
boolean allLower = true;
for (int index = 0; index < colon; index++) {
char ch = inUrl.charAt(index);
if (!Character.isLetter(ch)) {
break;
}
allLower &= Character.isLowerCase(ch);
if (index == colon - 1 && !allLower) {
inUrl = inUrl.substring(0, colon).toLowerCase()
+ inUrl.substring(colon);
}
}
if (inUrl.startsWith("http://") || inUrl.startsWith("https://"))
return inUrl;
if (inUrl.startsWith("http:") ||
inUrl.startsWith("https:")) {
if (inUrl.startsWith("http:/") || inUrl.startsWith("https:/")) {
inUrl = inUrl.replaceFirst("/", "//");
} else inUrl = inUrl.replaceFirst(":", "://");
}
return inUrl;
}
/**
* Formats a launch-able uri out of the template uri by replacing the template parameters with
* actual values.
*/
public static String getFormattedUri(String templateUri, String query) {
if (templateUri.isEmpty()) {
return null;
}
// Encode the query terms in the UTF-8 encoding
try {
return templateUri.replace("{searchTerms}", URLEncoder.encode(query, "UTF-8"));
} catch (UnsupportedEncodingException e) {
Log.e(TAG, "Exception occurred when encoding query " + query + " to UTF-8");
return null;
}
}
}

@ -0,0 +1,104 @@
/*
* Copyright (C) 2017 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.lineageos.jelly.webview;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.view.View;
import android.webkit.GeolocationPermissions;
import android.webkit.ValueCallback;
import android.webkit.WebChromeClient;
import android.webkit.WebView;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.Toast;
import org.lineageos.jelly.MainActivity;
import org.lineageos.jelly.R;
import org.lineageos.jelly.history.HistoryDatabaseHandler;
import org.lineageos.jelly.history.HistoryItem;
class ChromeClient extends WebChromeClient {
private final Context mContext;
private final HistoryDatabaseHandler mHistoryHandler;
private final boolean mIncognito;
private EditText mEditText;
private ProgressBar mProgressBar;
ChromeClient(Context context, boolean incognito) {
super();
mContext = context;
mHistoryHandler = new HistoryDatabaseHandler(context);
mIncognito = incognito;
}
@Override
public void onProgressChanged(WebView view, int progress) {
mProgressBar.setVisibility(progress == 100 ? View.INVISIBLE : View.VISIBLE);
mProgressBar.setProgress(progress == 100 ? 0 : progress);
super.onProgressChanged(view, progress);
}
@Override
public void onReceivedTitle(WebView view, String title) {
mEditText.setText(view.getUrl());
mHistoryHandler.addItem(new HistoryItem(title, view.getUrl()));
}
@Override
public void onReceivedIcon(WebView view, Bitmap icon) {
((MainActivity) mContext).setColor(icon, mIncognito);
}
@Override
public boolean onShowFileChooser(WebView view, ValueCallback<Uri[]> path,
FileChooserParams params) {
Intent intent = params.createIntent();
try {
((MainActivity) mContext).startActivityForResult(intent, MainActivity.FILE_CHOOSER_REQ);
} catch (ActivityNotFoundException e) {
Toast.makeText(mContext, mContext.getString(R.string.error_no_activity_found),
Toast.LENGTH_LONG).show();
return false;
}
return true;
}
@Override
public void onGeolocationPermissionsShowPrompt(String origin,
GeolocationPermissions.Callback callback) {
MainActivity activity = ((MainActivity) mContext);
if (activity.hasLocationPermission()) {
activity.requestLocationPermission();
} else {
callback.invoke(origin, true, false);
}
}
void bindEditText(EditText editText) {
mEditText = editText;
}
void bindProgressBar(ProgressBar progressBar) {
mProgressBar = progressBar;
}
}

@ -0,0 +1,53 @@
/*
* Copyright (C) 2017 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.lineageos.jelly.webview;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.support.design.widget.Snackbar;
import android.webkit.WebResourceRequest;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import org.lineageos.jelly.R;
class WebClient extends WebViewClient {
WebClient() {
super();
}
@Override
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
String url = request.getUrl().toString();
Context context = view.getContext();
if (!url.startsWith("http")) {
try {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(request.getUrl());
context.startActivity(intent);
} catch (ActivityNotFoundException e) {
Snackbar.make(view, context.getString(R.string.error_no_activity_found),
Snackbar.LENGTH_LONG).show();
}
return true;
}
return false;
}
}

@ -0,0 +1,141 @@
/*
* Copyright (C) 2017 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.lineageos.jelly.webview;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.Patterns;
import android.view.View;
import android.webkit.URLUtil;
import android.webkit.WebView;
import android.widget.EditText;
import android.widget.ProgressBar;
import org.lineageos.jelly.MainActivity;
import org.lineageos.jelly.utils.PrefsUtils;
import org.lineageos.jelly.utils.UrlUtils;
public class WebViewExt extends WebView {
private final Context mContext;
public WebViewExt(Context context) {
super(context);
mContext = context;
setup();
}
public WebViewExt(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
setup();
}
public WebViewExt(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mContext = context;
setup();
}
@Override
public void loadUrl(String url) {
// Try to add http prefix
if (!url.startsWith("http")) {
String withHttp = "http://" + url;
if ((Patterns.WEB_URL.matcher(withHttp).matches() ||
UrlUtils.ACCEPTED_URI_SCHEMA.matcher(withHttp).matches()) &&
withHttp.contains(".")) {
super.loadUrl(withHttp);
return;
}
}
// http url
String query = UrlUtils.fixUrl(url).trim();
if (Patterns.WEB_URL.matcher(query).matches() ||
UrlUtils.ACCEPTED_URI_SCHEMA.matcher(query).matches() ||
query.isEmpty()) {
super.loadUrl(url);
return;
}
// Query
String baseUrl = PrefsUtils.getSearchEngine(mContext);
super.loadUrl(UrlUtils.getFormattedUri(baseUrl, query));
}
private void setup() {
getSettings().setJavaScriptEnabled(PrefsUtils.getJavascript(mContext));
getSettings().setGeolocationEnabled(PrefsUtils.getLocation(mContext));
getSettings().setBuiltInZoomControls(true);
getSettings().setDisplayZoomControls(false);
setWebViewClient(new WebClient());
setOnLongClickListener(new OnLongClickListener() {
boolean shouldAllowDownload;
@Override
public boolean onLongClick(View v) {
HitTestResult result = getHitTestResult();
switch (result.getType()) {
case HitTestResult.IMAGE_TYPE:
case HitTestResult.SRC_IMAGE_ANCHOR_TYPE:
shouldAllowDownload = true;
case HitTestResult.SRC_ANCHOR_TYPE:
((MainActivity) mContext).showSheetMenu(result.getExtra(),
shouldAllowDownload);
shouldAllowDownload = false;
return true;
}
return false;
}
});
setDownloadListener((url, userAgent, contentDescription, mimeType, contentLength) ->
((MainActivity) mContext).downloadFileAsk(url,
URLUtil.guessFileName(url, contentDescription, mimeType)));
}
public void init(Context context, EditText editText,
ProgressBar progressBar, boolean incognito) {
ChromeClient chromeClient = new ChromeClient(context, incognito);
chromeClient.bindEditText(editText);
chromeClient.bindProgressBar(progressBar);
setWebChromeClient(chromeClient);
}
public Bitmap getSnap() {
measure(MeasureSpec.makeMeasureSpec(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED),
MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
layout(0, 0, getMeasuredWidth(), getMeasuredHeight());
setDrawingCacheEnabled(true);
buildDrawingCache();
int size = getMeasuredWidth() > getMeasuredHeight() ?
getMeasuredHeight() : getMeasuredWidth();
Bitmap bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint();
int height = bitmap.getHeight();
canvas.drawBitmap(bitmap, 0, height, paint);
draw(canvas);
return bitmap;
}
}

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2017 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="@color/empty_background" />
<size
android:width="120dp"
android:height="120dp" />
</shape>

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2017 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M20,11H7.83l5.59,-5.59L12,4l-8,8 8,8 1.41,-1.41L7.83,13H20v-2z"/>
</vector>

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2017 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="@color/menu_icon"
android:pathData="M6,19c0,1.1 0.9,2 2,2h8c1.1,0 2,-0.9 2,-2V7H6v12zM19,4h-3.5l-1,-1h-5l-1,1H5v2h14V4z"/>
</vector>

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2017 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M19,9h-4V3H9v6H5l7,7 7,-7zM5,18v2h14v-2H5z"/>
</vector>

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2017 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="@color/menu_icon"
android:pathData="M12,21.35l-1.45,-1.32C5.4,15.36 2,12.28 2,8.5 2,5.42 4.42,3 7.5,3c1.74,0 3.41,0.81 4.5,2.09C13.09,3.81 14.76,3 16.5,3 19.58,3 22,5.42 22,8.5c0,3.78 -3.4,6.86 -8.55,11.54L12,21.35z"/>
</vector>

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2017 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="@color/menu_icon"
android:pathData="M 8,13 L 11,13 L 11,16 L 13,16 L 13,13 L 16,13 L 16,11 L 13,11 L 13,8 L 11,8 L 11,11 L 8,11 L 8,13 M16.5,3c-1.74,0 -3.41,0.81 -4.5,2.09C10.91,3.81 9.24,3 7.5,3 4.42,3 2,5.42 2,8.5c0,3.78 3.4,6.86 8.55,11.54L12,21.35l1.45,-1.32C18.6,15.36 22,12.28 22,8.5 22,5.42 19.58,3 16.5,3zM12.1,18.55l-0.1,0.1 -0.1,-0.1C7.14,14.24 4,11.39 4,8.5 4,6.5 5.5,5 7.5,5c1.54,0 3.04,0.99 3.57,2.36h1.87C13.46,5.99 14.96,5 16.5,5c2,0 3.5,1.5 3.5,3.5 0,2.89 -3.14,5.74 -7.9,10.05z"/>
</vector>

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2017 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="@color/menu_icon"
android:pathData="M13,3c-4.97,0 -9,4.03 -9,9L1,12l3.89,3.89 0.07,0.14L9,12L6,12c0,-3.87 3.13,-7 7,-7s7,3.13 7,7 -3.13,7 -7,7c-1.93,0 -3.68,-0.79 -4.94,-2.06l-1.42,1.42C8.27,19.99 10.51,21 13,21c4.97,0 9,-4.03 9,-9s-4.03,-9 -9,-9zM12,8v5l4.28,2.54 0.72,-1.21 -3.5,-2.08L13.5,8L12,8z"/>
</vector>

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2017 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="@color/menu_icon"
android:pathData="M12,3C9.31,3 7.41,4.22 7.41,4.22L6,9H18L16.59,4.22C16.59,4.22 14.69,3 12,3M12,11C9.27,11 5.39,11.54 5.13,11.59C4.09,11.87 3.25,12.15 2.59,12.41C1.58,12.75 1,13 1,13H23C23,13 22.42,12.75 21.41,12.41C20.75,12.15 19.89,11.87 18.84,11.59C18.84,11.59 14.82,11 12,11M7.5,14A3.5,3.5 0 0,0 4,17.5A3.5,3.5 0 0,0 7.5,21A3.5,3.5 0 0,0 11,17.5C11,17.34 11,17.18 10.97,17.03C11.29,16.96 11.63,16.9 12,16.91C12.37,16.91 12.71,16.96 13.03,17.03C13,17.18 13,17.34 13,17.5A3.5,3.5 0 0,0 16.5,21A3.5,3.5 0 0,0 20,17.5A3.5,3.5 0 0,0 16.5,14C15.03,14 13.77,14.9 13.25,16.19C12.93,16.09 12.55,16 12,16C11.45,16 11.07,16.09 10.75,16.19C10.23,14.9 8.97,14 7.5,14M7.5,15A2.5,2.5 0 0,1 10,17.5A2.5,2.5 0 0,1 7.5,20A2.5,2.5 0 0,1 5,17.5A2.5,2.5 0 0,1 7.5,15M16.5,15A2.5,2.5 0 0,1 19,17.5A2.5,2.5 0 0,1 16.5,20A2.5,2.5 0 0,1 14,17.5A2.5,2.5 0 0,1 16.5,15Z" />
</vector>

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2017 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="@color/menu_icon"
android:pathData="M12,8c1.1,0 2,-0.9 2,-2s-0.9,-2 -2,-2 -2,0.9 -2,2 0.9,2 2,2zM12,10c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2zM12,16c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2z"/>
</vector>

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2017 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="@color/menu_icon"
android:pathData="M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/>
</vector>

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2017 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="@color/menu_icon"
android:pathData="M17.65,6.35C16.2,4.9 14.21,4 12,4c-4.42,0 -7.99,3.58 -7.99,8s3.57,8 7.99,8c3.73,0 6.84,-2.55 7.73,-6h-2.08c-0.82,2.33 -3.04,4 -5.65,4 -3.31,0 -6,-2.69 -6,-6s2.69,-6 6,-6c1.66,0 3.14,0.69 4.22,1.78L13,11h7V4l-2.35,2.35z"/>
</vector>

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2017 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="@color/menu_icon"
android:pathData="M19.43,12.98c0.04,-0.32 0.07,-0.64 0.07,-0.98s-0.03,-0.66 -0.07,-0.98l2.11,-1.65c0.19,-0.15 0.24,-0.42 0.12,-0.64l-2,-3.46c-0.12,-0.22 -0.39,-0.3 -0.61,-0.22l-2.49,1c-0.52,-0.4 -1.08,-0.73 -1.69,-0.98l-0.38,-2.65C14.46,2.18 14.25,2 14,2h-4c-0.25,0 -0.46,0.18 -0.49,0.42l-0.38,2.65c-0.61,0.25 -1.17,0.59 -1.69,0.98l-2.49,-1c-0.23,-0.09 -0.49,0 -0.61,0.22l-2,3.46c-0.13,0.22 -0.07,0.49 0.12,0.64l2.11,1.65c-0.04,0.32 -0.07,0.65 -0.07,0.98s0.03,0.66 0.07,0.98l-2.11,1.65c-0.19,0.15 -0.24,0.42 -0.12,0.64l2,3.46c0.12,0.22 0.39,0.3 0.61,0.22l2.49,-1c0.52,0.4 1.08,0.73 1.69,0.98l0.38,2.65c0.03,0.24 0.24,0.42 0.49,0.42h4c0.25,0 0.46,-0.18 0.49,-0.42l0.38,-2.65c0.61,-0.25 1.17,-0.59 1.69,-0.98l2.49,1c0.23,0.09 0.49,0 0.61,-0.22l2,-3.46c0.12,-0.22 0.07,-0.49 -0.12,-0.64l-2.11,-1.65zM12,15.5c-1.93,0 -3.5,-1.57 -3.5,-3.5s1.57,-3.5 3.5,-3.5 3.5,1.57 3.5,3.5 -1.57,3.5 -3.5,3.5z"/>
</vector>

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2017 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="@color/menu_icon"
android:pathData="M18,16.08c-0.76,0 -1.44,0.3 -1.96,0.77L8.91,12.7c0.05,-0.23 0.09,-0.46 0.09,-0.7s-0.04,-0.47 -0.09,-0.7l7.05,-4.11c0.54,0.5 1.25,0.81 2.04,0.81 1.66,0 3,-1.34 3,-3s-1.34,-3 -3,-3 -3,1.34 -3,3c0,0.24 0.04,0.47 0.09,0.7L8.04,9.81C7.5,9.31 6.79,9 6,9c-1.66,0 -3,1.34 -3,3s1.34,3 3,3c0.79,0 1.5,-0.31 2.04,-0.81l7.12,4.16c-0.05,0.21 -0.08,0.43 -0.08,0.65 0,1.61 1.31,2.92 2.92,2.92 1.61,0 2.92,-1.31 2.92,-2.92s-1.31,-2.92 -2.92,-2.92z"/>
</vector>

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2017 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="@color/menu_icon"
android:pathData="M16,8h-2v3h-3v2h3v3h2v-3h3v-2h-3zM2,12c0,-2.79 1.64,-5.2 4.01,-6.32L6.01,3.52C2.52,4.76 0,8.09 0,12s2.52,7.24 6.01,8.48v-2.16C3.64,17.2 2,14.79 2,12zM15,3c-4.96,0 -9,4.04 -9,9s4.04,9 9,9 9,-4.04 9,-9 -4.04,-9 -9,-9zM15,19c-3.86,0 -7,-3.14 -7,-7s3.14,-7 7,-7 7,3.14 7,7 -3.14,7 -7,7z"/>
</vector>

@ -0,0 +1,57 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2017 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/coordinator_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?colorPrimary" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="?actionBarSize">
<android.support.v7.widget.RecyclerView
android:id="@+id/favorite_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingEnd="12dp"
android:paddingStart="12dp"
android:scrollbars="vertical" />
<LinearLayout
android:id="@+id/favorite_empty_layout"
style="@style/AppTheme.EmptyLayout"
tools:ignore="UseCompoundDrawables">
<ImageView
style="@style/AppTheme.EmptyImage"
android:src="@drawable/ic_favorite"
android:tint="@color/empty_image" />
<TextView
style="@style/AppTheme.EmptyText"
android:text="@string/favorite_empty" />
</LinearLayout>
</RelativeLayout>
</android.support.design.widget.CoordinatorLayout>

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2017 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/coordinator_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?colorPrimary" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="?actionBarSize">
<android.support.v7.widget.RecyclerView
android:id="@+id/history_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical" />
<LinearLayout
android:id="@+id/history_empty_layout"
style="@style/AppTheme.EmptyLayout"
tools:ignore="UseCompoundDrawables">
<ImageView
style="@style/AppTheme.EmptyImage"
android:src="@drawable/ic_history"
android:tint="@color/empty_image" />
<TextView
style="@style/AppTheme.EmptyText"
android:text="@string/history_empty" />
</LinearLayout>
</RelativeLayout>
</android.support.design.widget.CoordinatorLayout>

@ -0,0 +1,70 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2017 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/coordinator_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
style="@style/AppTheme.ToolbarTheme"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimaryDark"
app:popupTheme="@style/AppTheme.PopupOverlay">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ProgressBar
android:id="@+id/load_progress"
style="@style/Widget.AppCompat.ProgressBar.Horizontal"
android:layout_width="match_parent"
android:layout_height="2dp"
android:layout_alignParentBottom="true"
android:max="100"
android:paddingTop="2dp"
android:progress="54" />
<include
layout="@layout/search_bar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@id/load_progress" />
</RelativeLayout>
</android.support.v7.widget.Toolbar>
</android.support.design.widget.AppBarLayout>
<android.support.v4.widget.SwipeRefreshLayout
android:id="@+id/swipe_refresh"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="?actionBarSize">
<org.lineageos.jelly.webview.WebViewExt
android:id="@+id/web_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</android.support.v4.widget.SwipeRefreshLayout>
</android.support.design.widget.CoordinatorLayout>

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2017 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?colorPrimary" />
<fragment
android:name="org.lineageos.jelly.SettingsActivity$MyPreferenceFragment"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/toolbar"
android:tag="org.lineageos.jelly.SettingsActivity$MyPreferenceFragment" />
</RelativeLayout>

@ -0,0 +1,51 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2017 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="8dp"
android:paddingEnd="24dp"
android:paddingStart="24dp"
android:paddingTop="16dp">
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="8dp">
<org.lineageos.jelly.ui.EditTextExt
android:id="@+id/favorite_edit_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/favorite_edit_title" />
</android.support.design.widget.TextInputLayout>
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:errorTextAppearance="@string/favorite_edit_error">
<org.lineageos.jelly.ui.EditTextExt
android:id="@+id/favorite_edit_url"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/favorite_edit_url"
android:inputType="textUri" />
</android.support.design.widget.TextInputLayout>
</LinearLayout>

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2017 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/row_favorite_card"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="4dp"
android:foreground="?selectableItemBackground"
android:orientation="vertical"
app:contentPadding="8dp">
<TextView
android:id="@+id/row_favorite_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:ellipsize="end"
android:maxLines="2"
android:paddingBottom="12dp"
android:paddingTop="12dp"
android:textAlignment="center"
android:textSize="18sp" />
</android.support.v7.widget.CardView>

@ -0,0 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2017 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/row_history_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:foreground="?selectableItemBackground"
android:gravity="center_vertical"
android:minHeight="60dp"
android:orientation="vertical"
android:paddingEnd="16dp"
android:paddingStart="16dp">
<TextView
android:id="@+id/row_history_title"
style="@android:style/TextAppearance.Medium"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="marquee"
android:maxLines="1" />
<TextView
android:id="@+id/row_history_summary"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>

@ -0,0 +1,73 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2017 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:paddingBottom="4dp"
android:paddingEnd="16dp"
android:paddingStart="16dp"
android:paddingTop="4dp">
<!-- Dummy view to catch focus -->
<View
android:layout_width="0dp"
android:layout_height="0dp"
android:focusable="true"
android:focusableInTouchMode="true" />
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:cardBackgroundColor="@color/cardview_light_background"
app:cardElevation="4dp"
app:contentPadding="2dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageButton
android:id="@+id/search_menu"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentEnd="true"
android:adjustViewBounds="true"
android:background="?selectableItemBackgroundBorderless"
android:padding="8dp"
android:src="@drawable/ic_menu" />
<org.lineageos.jelly.ui.EditTextExt
android:id="@+id/url_bar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentStart="true"
android:layout_toStartOf="@id/search_menu"
android:background="@null"
android:fadingEdge="vertical"
android:imeOptions="actionSearch"
android:inputType="textUri"
android:maxLines="1"
android:nextFocusLeft="@id/url_bar"
android:nextFocusUp="@id/url_bar"
android:paddingStart="4dp"
android:textColor="@android:color/black"
tools:ignore="RtlSymmetry" />
</RelativeLayout>
</android.support.v7.widget.CardView>
</RelativeLayout>

@ -0,0 +1,78 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2017 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="180dp"
android:orientation="vertical"
app:layout_behavior="android.support.design.widget.BottomSheetBehavior"
tools:ignore="UseCompoundDrawables">
<LinearLayout
android:id="@+id/sheet_new_tab"
style="@style/AppTheme.BottomSheetLayout">
<ImageView
style="@style/AppTheme.BottomSheetIcon"
android:src="@drawable/ic_new_tab" />
<TextView
style="@style/AppTheme.BottomSheetText"
android:text="@string/menu_in_new_tab" />
</LinearLayout>
<LinearLayout
android:id="@+id/sheet_share"
style="@style/AppTheme.BottomSheetLayout">
<ImageView
style="@style/AppTheme.BottomSheetIcon"
android:src="@drawable/ic_share" />
<TextView
style="@style/AppTheme.BottomSheetText"
android:text="@string/menu_share" />
</LinearLayout>
<LinearLayout
android:id="@+id/sheet_favourite"
style="@style/AppTheme.BottomSheetLayout">
<ImageView
style="@style/AppTheme.BottomSheetIcon"
app:srcCompat="@drawable/ic_favorite_add" />
<TextView
style="@style/AppTheme.BottomSheetText"
android:text="@string/menu_fav_add" />
</LinearLayout>
<LinearLayout
android:id="@+id/sheet_download"
style="@style/AppTheme.BottomSheetLayout"
android:visibility="gone">
<ImageView
style="@style/AppTheme.BottomSheetIcon"
app:srcCompat="@drawable/ic_download" />
<TextView
style="@style/AppTheme.BottomSheetText"
android:text="@string/menu_download" />
</LinearLayout>
</LinearLayout>

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2017 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/menu_history_delete"
android:icon="@drawable/ic_delete"
android:title="@string/history_delete_title"
app:showAsAction="ifRoom" />
</menu>

@ -0,0 +1,63 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2017 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/menu_new"
android:icon="@drawable/ic_new_tab"
android:title="@string/menu_new_tab"
app:showAsAction="never" />
<item
android:id="@+id/menu_incognito"
android:icon="@drawable/ic_incognito"
android:title="@string/menu_incognito"
app:showAsAction="never" />
<item
android:id="@+id/menu_reload"
android:icon="@drawable/ic_refresh"
android:title="@string/menu_reload"
app:showAsAction="never" />
<item
android:id="@+id/menu_add_favorite"
android:icon="@drawable/ic_favorite_add"
android:title="@string/menu_fav_add"
app:showAsAction="never" />
<item
android:id="@+id/menu_share"
android:icon="@drawable/ic_share"
android:title="@string/menu_share"
app:showAsAction="never" />
<item
android:id="@+id/menu_favorite"
android:icon="@drawable/ic_favorite"
android:title="@string/menu_favorites"
app:showAsAction="never" />
<item
android:id="@+id/menu_history"
android:icon="@drawable/ic_history"
android:title="@string/menu_history"
app:showAsAction="never" />
<item
android:id="@+id/menu_shortcut"
android:icon="@drawable/ic_shortcut"
android:title="@string/menu_shortcut"
app:showAsAction="never" />
<item
android:id="@+id/menu_settings"
android:icon="@drawable/ic_settings"
android:title="@string/menu_settings"
app:showAsAction="never" />
</menu>

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2017 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources>
<color name="colorPrimary">#fafafa</color>
<color name="colorPrimaryDark">#E0E0E0</color>
<color name="colorAccent">#FF4081</color>
<color name="colorIncognito">#000b4d</color>
<color name="menu_icon">#333333</color>
<color name="empty_image">#b1b1b1</color>
<color name="empty_background">#efefef</color>
<color name="empty_text">@color/empty_image</color>
<color name="history_last_hour">#fafafa</color>
<color name="history_today">#f6f6f6</color>
<color name="history_this_week">#f0f0f0</color>
<color name="history_this_month">#eeeeee</color>
<color name="history_earlier">#e5e5e5</color>
</resources>

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2017 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources>
<string-array name="pref_search_engine_entries" translatable="false">
<item>Baidu</item>
<item>Bing</item>
<item>DuckDuckGo</item>
<item>Google</item>
<item>Yahoo</item>
</string-array>
<string-array name="pref_search_engine_entryvalues" translatable="false">
<item>https://www.baidu.com/s?wd={searchTerms}</item>
<item>https://www.bing.com/search?q={searchTerms}</item>
<item>https://duckduckgo.com/?q={searchTerms}</item>
<item>https://encrypted.google.com/search?q={searchTerms}</item>
<item>https://search.yahoo.com/p={searchTerms}</item>
</string-array>
</resources>

@ -0,0 +1,136 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2017 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources>
<string name="app_name">Browser</string>
<!-- Menu action: create new tab -->
<string name="menu_new_tab">New tab</string>
<!-- Menu action: create new incognito tab -->
<string name="menu_incognito">Incognito tab</string>
<!-- Menu action: reload current page -->
<string name="menu_reload">Reload</string>
<!-- Menu action: add current page to favorites -->
<string name="menu_fav_add">Add to favorites</string>
<!-- Menu action: share current page -->
<string name="menu_share">Share</string>
<!-- Menu action: show favorites list -->
<string name="menu_favorites">Favorites</string>
<!-- Menu action: show history list -->
<string name="menu_history">History</string>
<!-- Menu action: add shortcut of the current page to the launcher -->
<string name="menu_shortcut">Add shortcut</string>
<!-- Menu action: show settings -->
<string name="menu_settings">Settings</string>
<!-- Menu action: download selected file / image -->
<string name="menu_download">Download</string>
<!-- Menu action: open selected link in a new tab -->
<string name="menu_in_new_tab">Open in new tab</string>
<!-- Dialog action: dismiss -->
<string name="dismiss">Dismiss</string>
<!-- Download dialog: title -->
<string name="download_title">Download file</string>
<!-- Download dialog: message -->
<string name="download_message">Do you want to download %1$s to the sdcard?</string>
<!-- Download dialog: button that starts the download -->
<string name="download_positive">Download</string>
<!-- Permission error dialog: title -->
<string name="permission_error_title">Permission error</string>
<!-- Permission error dialog: message for denied storage access-->
<string name="permission_error_storage">Browser needs storage access to download files. Please grant it to save files from the web</string>
<!-- Permission error dialog: button that triggers permission request again -->
<string name="permission_error_ask_again">Ask again</string>
<!-- Permission error snackBar: the permission has been denied until user enables it in settings -->
<string name="permission_error_forever">Permission denied forever. Please grant it in settings</string>
<!-- Shortcut: the current webPage has been added to the launcher -->
<string name="shortcut_added">Added to the home screen</string>
<!-- Settings: title -->
<string name="settings_title">Settings</string>
<!-- Settings: search engine preference title -->
<string name="pref_search_engine">Search engine</string>
<!-- Settings: home page preference title -->
<string name="pref_start_page">Home page</string>
<!-- Settings: select home page dialog title -->
<string name="pref_start_page_dialog_title">Select home page</string>
<!-- Settings: select home page dialog message -->
<string name="pref_start_page_dialog_message">Write the home page url</string>
<!-- Settings: privacy and security category -->
<string name="pref_privacy_security">Privacy &amp; security</string>
<!-- Settings: lookLock title -->
<string name="pref_looklock_title">LookLock</string>
<!-- Settings: lookLock summary -->
<string name="pref_looklock_summary">Prevent other apps from reading Browser\'s content</string>
<!-- Settings: javascript preference title -->
<string name="pref_js_title">Javascript</string>
<!-- Settings: javascript preference summary -->
<string name="pref_js_summary">Enable javascript</string>
<!-- Settings: location preference title -->
<string name="pref_location_title">Location</string>
<!-- Settings: location preference summary. Note that this doesn't allow permission access to the websites, but just allows the possibility of requesting access to it -->
<string name="pref_location_summary">Allow websites to request access to your location</string>
<!-- Settings: cookie preference title -->
<string name="pref_cookie_title">Cookies</string>
<!-- Settings: cookie preference summary -->
<string name="pref_cookie_summary">Allow websites to save and load cookies</string>
<!-- Settings: advanced share preference title -->
<string name="pref_screenshot_snap_title">Advanced share</string>
<!-- Settings: advanced share preference summary -->
<string name="pref_screenshot_snap_summary">Share preview of the shared WebPage</string>
<!-- History: title -->
<string name="history_title">History</string>
<!-- History: empty status text -->
<string name="history_empty">There\'s nothing here, browse on the internet to see your history here</string>
<!-- History: date format for items. EEEE = day (Monday), MMMM = month (January), yyyy = year (1970), HH = hour (12), mm = minutes (30) -->
<string name="history_date_format">EEEE MMMM dd yyyy, HH:mm</string>
<!-- History: delete history dialog title -->
<string name="history_delete_title">Clear history</string>
<!-- History: delete history dialog warning message -->
<string name="history_delete_message">You\'re going to delete all the history, this action cannot be undone. Do you want to proceed?</string>
<!-- History: delete history dialog button that erases all the history -->
<string name="history_delete_positive">Clear</string>
<!-- History: delete history "working" dialog-->
<string name="history_deleting_message">Clearing history\u2026</string>
<!-- Favorite: title -->
<string name="favorite_title">Favorites</string>
<!-- Favorite: snackBar message shown when an url is added to favorites -->
<string name="favorite_added">Added to favorites</string>
<!-- Favorite: empty status text -->
<string name="favorite_empty">There\'s nothing here, add a favorite link to see it here</string>
<!-- Favorite: edit dialog title -->
<string name="favorite_edit_dialog_title">Edit favorite</string>
<!-- Favorite: edit dialog: title of the favorite -->
<string name="favorite_edit_title">Title</string>
<!-- Favorite: edit dialog: url of the favorite-->
<string name="favorite_edit_url">Url</string>
<!-- Favorite: edit dialog positive button that save changes -->
<string name="favorite_edit_positive">Edit</string>
<!-- Favorite: edit dialog button that deletes the selected favorite -->
<string name="favorite_edit_delete">Delete</string>
<!-- Favorite: edit dialog: invalid url error message -->
<string name="favorite_edit_error">Insert a valid url</string>
<!-- No activity found to open the given url error -->
<string name="error_no_activity_found">No app can handle this link</string>
<string translatable="false" name="default_search_engine">https://duckduckgo.com/?q={searchTerms}</string>
<string translatable="false" name="default_home_page">https://duckduckgo.com</string>
</resources>

@ -0,0 +1,94 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2017 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources>
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="android:windowLightStatusBar">true</item>
</style>
<style name="AppTheme.NoActionBar">
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
</style>
<style name="AppTheme.ToolbarTheme" parent="Widget.AppCompat.Toolbar">
<item name="contentInsetStart">0dp</item>
</style>
<style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />
<style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />
<style name="AppTheme.PopupMenuOverlapAnchor">
<item name="android:overlapAnchor">true</item>
<item name="android:dropDownVerticalOffset">0dp</item>
<item name="android:dropDownHorizontalOffset">0dp</item>
</style>
<style name="AppTheme.BottomSheetLayout">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">60dp</item>
<item name="android:clickable">true</item>
<item name="android:focusable">true</item>
<item name="android:foreground">?android:attr/selectableItemBackground</item>
<item name="android:orientation">horizontal</item>
<item name="android:padding">16dp</item>
</style>
<style name="AppTheme.BottomSheetIcon">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">match_parent</item>
<item name="android:contentDescription">@null</item>
<item name="android:tint">@color/menu_icon</item>
</style>
<style name="AppTheme.BottomSheetText">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_gravity">center</item>
<item name="android:layout_marginStart">16dp</item>
</style>
<style name="AppTheme.EmptyLayout">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">match_parent</item>
<item name="android:gravity">center</item>
<item name="android:orientation">vertical</item>
<item name="android:visibility">gone</item>
</style>
<style name="AppTheme.EmptyImage">
<item name="android:layout_width">120dp</item>
<item name="android:layout_height">120dp</item>
<item name="android:background">@drawable/empty_background</item>
<item name="android:padding">8dp</item>
<item name="android:scaleType">fitXY</item>
</style>
<style name="AppTheme.EmptyText">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:paddingEnd">64dp</item>
<item name="android:paddingStart">64dp</item>
<item name="android:paddingTop">19dp</item>
<item name="android:textAlignment">center</item>
<item name="android:textColor">@color/empty_text</item>
<item name="android:textSize">14sp</item>
</style>
</resources>

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2017 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<full-backup-content>
<!-- Shared preferences -->
<include
domain="sharedpref"
path="org.lineageos.jelly_preferences.xml" />
<!-- Databases -->
<include
domain="database"
path="HistoryDatabase" />
<include
domain="database"
path="FavoriteDatabase" />
</full-backup-content>

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2017 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<paths>
<cache-path
name="all_dirs"
path="." />
</paths>

@ -0,0 +1,65 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2017 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<ListPreference
android:defaultValue="@string/default_search_engine"
android:entries="@array/pref_search_engine_entries"
android:entryValues="@array/pref_search_engine_entryvalues"
android:key="key_search_engine"
android:summary="%s"
android:title="@string/pref_search_engine" />
<EditTextPreference
android:defaultValue="@string/default_home_page"
android:dialogMessage="@string/pref_start_page_dialog_message"
android:dialogTitle="@string/pref_start_page_dialog_title"
android:key="key_home_page"
android:title="@string/pref_start_page" />
<SwitchPreference
android:defaultValue="0"
android:key="key_advanced_share"
android:summary="@string/pref_screenshot_snap_summary"
android:title="@string/pref_screenshot_snap_title" />
<PreferenceCategory android:title="@string/pref_privacy_security">
<SwitchPreference
android:defaultValue="0"
android:key="key_looklock"
android:summary="@string/pref_looklock_summary"
android:title="@string/pref_looklock_title" />
<SwitchPreference
android:defaultValue="1"
android:key="key_javascript"
android:summary="@string/pref_js_summary"
android:title="@string/pref_js_title" />
<SwitchPreference
android:defaultValue="1"
android:key="key_location"
android:summary="@string/pref_location_summary"
android:title="@string/pref_location_title" />
<SwitchPreference
android:defaultValue="1"
android:key="key_cookie"
android:summary="@string/pref_cookie_summary"
android:title="@string/pref_cookie_title" />
</PreferenceCategory>
</PreferenceScreen>

@ -0,0 +1,23 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.3.0'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
jcenter()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}

@ -0,0 +1,17 @@
# Project-wide Gradle settings.
# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
org.gradle.jvmargs=-Xmx1536m
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true

Binary file not shown.

@ -0,0 +1,6 @@
#Fri Apr 14 16:24:15 CEST 2017
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip

160
gradlew vendored

@ -0,0 +1,160 @@
#!/usr/bin/env bash
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn ( ) {
echo "$*"
}
die ( ) {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
esac
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
JVM_OPTS=("$@")
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"

90
gradlew.bat vendored

@ -0,0 +1,90 @@
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windowz variants
if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
goto execute
:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
set CMD_LINE_ARGS=%$
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

@ -0,0 +1 @@
include ':app'
Loading…
Cancel
Save