commit
b0f367f8aa
@ -0,0 +1,99 @@ |
||||
name: Build and Release |
||||
|
||||
on: |
||||
push: |
||||
branches: |
||||
- master |
||||
paths: |
||||
- 'CHANGELOG.md' |
||||
# schedule: |
||||
# - cron: '0 4 * * *' |
||||
|
||||
jobs: |
||||
build: |
||||
runs-on: ubuntu-latest |
||||
env: |
||||
# 登录蓝奏云后在控制台运行document.cookie |
||||
ylogin: ${{ secrets.LANZOU_ID }} |
||||
phpdisk_info: ${{ secrets.LANZOU_PSD }} |
||||
# 蓝奏云里的文件夹ID(阅读3测试版:2670621) |
||||
LANZOU_FOLDER_ID: 'b0f7pt4ja' |
||||
# 是否上传到artifact |
||||
UPLOAD_ARTIFACT: 'true' |
||||
steps: |
||||
- uses: actions/checkout@v2 |
||||
- uses: actions/cache@v2 |
||||
with: |
||||
path: | |
||||
~/.gradle/caches |
||||
~/.gradle/wrapper |
||||
key: ${{ runner.os }}-legado-${{ hashFiles('**/updateLog.md') }}-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} |
||||
restore-keys: | |
||||
${{ runner.os }}-legado-${{ hashFiles('**/updateLog.md') }}- |
||||
- name: Release Apk Sign |
||||
run: | |
||||
echo "给apk增加签名" |
||||
cp $GITHUB_WORKSPACE/.github/workflows/legado.jks $GITHUB_WORKSPACE/app/legado.jks |
||||
sed '$a\RELEASE_STORE_FILE=./legado.jks' $GITHUB_WORKSPACE/gradle.properties -i |
||||
sed '$a\RELEASE_KEY_ALIAS=legado' $GITHUB_WORKSPACE/gradle.properties -i |
||||
sed '$a\RELEASE_STORE_PASSWORD=gedoor_legado' $GITHUB_WORKSPACE/gradle.properties -i |
||||
sed '$a\RELEASE_KEY_PASSWORD=gedoor_legado' $GITHUB_WORKSPACE/gradle.properties -i |
||||
- name: Unify Version Name |
||||
run: | |
||||
echo "统一版本号" |
||||
VERSION=$(date -d "8 hour" -u +3.%y.%m%d%H) |
||||
echo "RELEASE_VERSION=$VERSION" >> $GITHUB_ENV |
||||
sed "/def version/c def version = \"$VERSION\"" $GITHUB_WORKSPACE/app/build.gradle -i |
||||
- name: Build With Gradle |
||||
run: | |
||||
echo "开始进行release构建" |
||||
chmod +x gradlew |
||||
./gradlew assembleAppRelease --build-cache --parallel |
||||
echo "开始进行cronet构建" |
||||
./gradlew assembleCronetRelease --build-cache --parallel |
||||
- name: Organize the Files |
||||
run: | |
||||
mkdir -p ${{ github.workspace }}/apk/ |
||||
cp -rf ${{ github.workspace }}/app/build/outputs/apk/*/*/*.apk ${{ github.workspace }}/apk/ |
||||
- name: Upload App To Artifact |
||||
if: ${{ env.UPLOAD_ARTIFACT != 'false' }} |
||||
uses: actions/upload-artifact@v2 |
||||
with: |
||||
name: legado apk |
||||
path: ${{ github.workspace }}/apk/*.apk |
||||
- name: Upload App To Lanzou |
||||
if: ${{ env.ylogin }} |
||||
run: | |
||||
path="$GITHUB_WORKSPACE/apk/" |
||||
python3 $GITHUB_WORKSPACE/.github/scripts/lzy_web.py "$path" "$LANZOU_FOLDER_ID" |
||||
echo "[$(date -u -d '+8 hour' '+%Y.%m.%d %H:%M:%S')] 分享链接: https://kunfei.lanzoux.com/b0f7pt4ja" |
||||
- name: Release |
||||
uses: softprops/action-gh-release@59c3b4891632ff9a897f99a91d7bc557467a3a22 |
||||
with: |
||||
name: legado_app_${{ env.RELEASE_VERSION }} |
||||
tag_name: ${{ env.RELEASE_VERSION }} |
||||
body_path: ${{ github.workspace }}/CHANGELOG.md |
||||
draft: false |
||||
prerelease: false |
||||
files: ${{ github.workspace }}/apk/*.apk |
||||
env: |
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
||||
- name: Push Assets To "release" Branch |
||||
run: | |
||||
cd $GITHUB_WORKSPACE/apk || exit 1 |
||||
git init |
||||
git config --local user.name "github-actions[bot]" |
||||
git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com" |
||||
git checkout -b release |
||||
git add *.apk |
||||
git commit -m "${{ env.RELEASE_VERSION }}" |
||||
git remote add origin "https://${{ github.actor }}:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}" |
||||
git push -f -u origin release |
||||
- name: Purge Jsdelivr Cache |
||||
run: | |
||||
result=$(curl -s https://purge.jsdelivr.net/gh/${{ github.repository }}@release/) |
||||
if echo $result |grep -q 'success.*true'; then |
||||
echo "jsdelivr缓存更新成功" |
||||
else |
||||
echo $result |
||||
fi |
@ -1,4 +1,4 @@ |
||||
# 1.0.0 (2020-02-09) |
||||
|
||||
|
||||
**2021/08/09** |
||||
|
||||
1. 修复选择文字不能选择单个文字的bug |
||||
2. |
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,7 @@ |
||||
package io.legado.app.data.entities.rule |
||||
|
||||
data class LogInRule( |
||||
val ui: HashMap<String, String>, |
||||
val logInUrl: String, |
||||
val checkJs: String |
||||
) |
@ -1,55 +0,0 @@ |
||||
package io.legado.app.ui.book.group |
||||
|
||||
import android.content.Context |
||||
import android.view.LayoutInflater |
||||
import io.legado.app.R |
||||
import io.legado.app.data.appDb |
||||
import io.legado.app.data.entities.BookGroup |
||||
import io.legado.app.databinding.DialogEditTextBinding |
||||
import io.legado.app.help.coroutine.Coroutine |
||||
import io.legado.app.lib.dialogs.alert |
||||
import io.legado.app.utils.requestInputMethod |
||||
|
||||
object GroupEdit { |
||||
|
||||
fun show(context: Context, layoutInflater: LayoutInflater, bookGroup: BookGroup) = context.run { |
||||
alert(title = getString(R.string.group_edit)) { |
||||
val alertBinding = DialogEditTextBinding.inflate(layoutInflater).apply { |
||||
textInputLayout.setHint(R.string.group_name) |
||||
editView.setText(bookGroup.groupName) |
||||
} |
||||
if (bookGroup.groupId >= 0) { |
||||
neutralButton(R.string.delete) { |
||||
deleteGroup(context, bookGroup) |
||||
} |
||||
} |
||||
customView { alertBinding.root } |
||||
yesButton { |
||||
alertBinding.editView.text?.toString()?.let { |
||||
bookGroup.groupName = it |
||||
Coroutine.async { |
||||
appDb.bookGroupDao.update(bookGroup) |
||||
} |
||||
} |
||||
} |
||||
noButton() |
||||
}.show().requestInputMethod() |
||||
} |
||||
|
||||
private fun deleteGroup(context: Context, bookGroup: BookGroup) = context.run { |
||||
alert(R.string.delete, R.string.sure_del) { |
||||
okButton { |
||||
Coroutine.async { |
||||
appDb.bookGroupDao.delete(bookGroup) |
||||
val books = appDb.bookDao.getBooksByGroup(bookGroup.groupId) |
||||
books.forEach { |
||||
it.group = it.group - bookGroup.groupId |
||||
} |
||||
appDb.bookDao.update(*books.toTypedArray()) |
||||
} |
||||
} |
||||
noButton() |
||||
}.show() |
||||
} |
||||
|
||||
} |
@ -0,0 +1,121 @@ |
||||
package io.legado.app.ui.book.group |
||||
|
||||
import android.os.Bundle |
||||
import android.view.LayoutInflater |
||||
import android.view.View |
||||
import android.view.ViewGroup |
||||
import androidx.fragment.app.FragmentManager |
||||
import androidx.fragment.app.viewModels |
||||
import io.legado.app.R |
||||
import io.legado.app.base.BaseDialogFragment |
||||
import io.legado.app.data.entities.BookGroup |
||||
import io.legado.app.databinding.DialogBookGroupEditBinding |
||||
import io.legado.app.lib.dialogs.alert |
||||
import io.legado.app.lib.theme.primaryColor |
||||
import io.legado.app.utils.* |
||||
import io.legado.app.utils.viewbindingdelegate.viewBinding |
||||
import splitties.views.onClick |
||||
|
||||
class GroupEditDialog : BaseDialogFragment() { |
||||
|
||||
companion object { |
||||
|
||||
fun start(fragmentManager: FragmentManager, bookGroup: BookGroup? = null) { |
||||
GroupEditDialog().apply { |
||||
arguments = Bundle().apply { |
||||
putParcelable("group", bookGroup) |
||||
} |
||||
}.show(fragmentManager, "bookGroupEdit") |
||||
} |
||||
|
||||
} |
||||
|
||||
private val binding by viewBinding(DialogBookGroupEditBinding::bind) |
||||
private val viewModel by viewModels<GroupViewModel>() |
||||
private var bookGroup: BookGroup? = null |
||||
val selectImage = registerForActivityResult(SelectImageContract()) { |
||||
it?.second?.let { uri -> |
||||
if (uri.isContentScheme()) { |
||||
binding.ivCover.load(uri.toString()) |
||||
} else { |
||||
binding.ivCover.load(uri.path) |
||||
} |
||||
} |
||||
} |
||||
|
||||
override fun onStart() { |
||||
super.onStart() |
||||
val dm = requireActivity().windowSize |
||||
dialog?.window?.setLayout( |
||||
(dm.widthPixels * 0.9).toInt(), |
||||
ViewGroup.LayoutParams.WRAP_CONTENT |
||||
) |
||||
} |
||||
|
||||
override fun onCreateView( |
||||
inflater: LayoutInflater, |
||||
container: ViewGroup?, |
||||
savedInstanceState: Bundle? |
||||
): View? { |
||||
return inflater.inflate(R.layout.dialog_book_group_edit, container) |
||||
} |
||||
|
||||
override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) { |
||||
binding.toolBar.setBackgroundColor(primaryColor) |
||||
bookGroup = arguments?.getParcelable("group") |
||||
bookGroup?.let { |
||||
binding.tieGroupName.setText(it.groupName) |
||||
binding.ivCover.load(it.cover) |
||||
} ?: let { |
||||
binding.toolBar.title = getString(R.string.add_group) |
||||
binding.btnDelete.gone() |
||||
binding.ivCover.load() |
||||
} |
||||
binding.run { |
||||
ivCover.onClick { |
||||
selectImage.launch(null) |
||||
} |
||||
btnCancel.onClick { |
||||
dismiss() |
||||
} |
||||
btnOk.onClick { |
||||
val groupName = tieGroupName.text?.toString() |
||||
if (groupName.isNullOrEmpty()) { |
||||
toastOnUi("分组名称不能为空") |
||||
} else { |
||||
bookGroup?.let { |
||||
it.groupName = groupName |
||||
it.cover = binding.ivCover.path |
||||
viewModel.upGroup(it) { |
||||
dismiss() |
||||
} |
||||
} ?: let { |
||||
viewModel.addGroup(groupName, binding.ivCover.path) { |
||||
dismiss() |
||||
} |
||||
} |
||||
} |
||||
|
||||
} |
||||
btnDelete.onClick { |
||||
deleteGroup { |
||||
bookGroup?.let { |
||||
viewModel.delGroup(it) { |
||||
dismiss() |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
private fun deleteGroup(ok: () -> Unit) { |
||||
alert(R.string.delete, R.string.sure_del) { |
||||
okButton { |
||||
ok.invoke() |
||||
} |
||||
noButton() |
||||
}.show() |
||||
} |
||||
|
||||
} |
@ -1,32 +0,0 @@ |
||||
package io.legado.app.utils |
||||
|
||||
import android.app.Activity.RESULT_OK |
||||
import android.content.Context |
||||
import android.content.Intent |
||||
import android.net.Uri |
||||
import androidx.activity.result.contract.ActivityResultContract |
||||
|
||||
object ActivityResultContractUtils { |
||||
|
||||
class SelectImage : ActivityResultContract<Int, Pair<Int?, Uri?>?>() { |
||||
|
||||
var requestCode: Int? = null |
||||
|
||||
override fun createIntent(context: Context, input: Int?): Intent { |
||||
requestCode = input |
||||
return Intent(Intent.ACTION_GET_CONTENT) |
||||
.addCategory(Intent.CATEGORY_OPENABLE) |
||||
.setType("image/*") |
||||
} |
||||
|
||||
override fun parseResult(resultCode: Int, intent: Intent?): Pair<Int?, Uri?>? { |
||||
if (resultCode == RESULT_OK) { |
||||
return Pair(requestCode, intent?.data) |
||||
} |
||||
return null |
||||
} |
||||
|
||||
} |
||||
|
||||
|
||||
} |
@ -0,0 +1,27 @@ |
||||
package io.legado.app.utils |
||||
|
||||
import android.app.Activity.RESULT_OK |
||||
import android.content.Context |
||||
import android.content.Intent |
||||
import android.net.Uri |
||||
import androidx.activity.result.contract.ActivityResultContract |
||||
|
||||
class SelectImageContract : ActivityResultContract<Int, Pair<Int?, Uri?>?>() { |
||||
|
||||
var requestCode: Int? = null |
||||
|
||||
override fun createIntent(context: Context, input: Int?): Intent { |
||||
requestCode = input |
||||
return Intent(Intent.ACTION_OPEN_DOCUMENT) |
||||
.addCategory(Intent.CATEGORY_OPENABLE) |
||||
.setType("image/*") |
||||
} |
||||
|
||||
override fun parseResult(resultCode: Int, intent: Intent?): Pair<Int?, Uri?>? { |
||||
if (resultCode == RESULT_OK) { |
||||
return Pair(requestCode, intent?.data) |
||||
} |
||||
return null |
||||
} |
||||
|
||||
} |
@ -0,0 +1,90 @@ |
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<androidx.constraintlayout.widget.ConstraintLayout 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:background="@color/background_menu"> |
||||
|
||||
<androidx.appcompat.widget.Toolbar |
||||
android:id="@+id/tool_bar" |
||||
android:layout_width="match_parent" |
||||
android:layout_height="wrap_content" |
||||
android:background="@color/background_menu" |
||||
android:elevation="5dp" |
||||
android:theme="?attr/actionBarStyle" |
||||
app:displayHomeAsUp="false" |
||||
app:fitStatusBar="false" |
||||
app:layout_constraintTop_toTopOf="parent" |
||||
app:popupTheme="@style/AppTheme.PopupOverlay" |
||||
app:title="@string/group_edit" |
||||
app:titleTextAppearance="@style/ToolbarTitle" /> |
||||
|
||||
<io.legado.app.ui.widget.image.CoverImageView |
||||
android:id="@+id/iv_cover" |
||||
android:layout_width="90dp" |
||||
android:layout_height="126dp" |
||||
android:layout_margin="6dp" |
||||
android:contentDescription="@string/img_cover" |
||||
android:scaleType="centerCrop" |
||||
android:src="@drawable/image_cover_default" |
||||
app:layout_constraintBottom_toBottomOf="parent" |
||||
app:layout_constraintLeft_toLeftOf="parent" |
||||
app:layout_constraintTop_toBottomOf="@+id/tool_bar" |
||||
tools:ignore="ImageContrastCheck" /> |
||||
|
||||
|
||||
<io.legado.app.ui.widget.text.TextInputLayout |
||||
android:id="@+id/til_group_name" |
||||
android:layout_width="0dp" |
||||
android:layout_height="wrap_content" |
||||
android:layout_margin="6dp" |
||||
android:hint="@string/group_name" |
||||
app:layout_constraintLeft_toRightOf="@+id/iv_cover" |
||||
app:layout_constraintRight_toRightOf="parent" |
||||
app:layout_constraintTop_toBottomOf="@+id/tool_bar" |
||||
app:layout_constraintBottom_toTopOf="@+id/btn_ok"> |
||||
|
||||
<io.legado.app.ui.widget.text.EditText |
||||
android:id="@+id/tie_group_name" |
||||
android:layout_width="match_parent" |
||||
android:layout_height="wrap_content" |
||||
android:singleLine="true" |
||||
tools:ignore="TouchTargetSizeCheck,SpeakableTextPresentCheck" /> |
||||
</io.legado.app.ui.widget.text.TextInputLayout> |
||||
|
||||
<io.legado.app.ui.widget.text.AccentTextView |
||||
android:id="@+id/btn_delete" |
||||
android:layout_width="wrap_content" |
||||
android:layout_height="wrap_content" |
||||
android:padding="12dp" |
||||
android:layout_marginLeft="12dp" |
||||
android:text="@string/delete" |
||||
app:layout_constraintBottom_toBottomOf="@id/btn_ok" |
||||
app:layout_constraintLeft_toRightOf="@+id/iv_cover" |
||||
app:layout_constraintTop_toTopOf="@+id/btn_ok" |
||||
tools:ignore="RtlHardcoded" /> |
||||
|
||||
<io.legado.app.ui.widget.text.AccentTextView |
||||
android:id="@+id/btn_ok" |
||||
android:layout_width="wrap_content" |
||||
android:layout_height="wrap_content" |
||||
android:padding="12dp" |
||||
android:layout_marginRight="12dp" |
||||
android:text="@string/ok" |
||||
app:layout_constraintBottom_toBottomOf="parent" |
||||
app:layout_constraintRight_toRightOf="parent" |
||||
app:layout_constraintTop_toBottomOf="@+id/til_group_name" |
||||
tools:ignore="RtlHardcoded" /> |
||||
|
||||
<io.legado.app.ui.widget.text.AccentTextView |
||||
android:id="@+id/btn_cancel" |
||||
android:layout_width="wrap_content" |
||||
android:layout_height="wrap_content" |
||||
android:padding="12dp" |
||||
android:text="@string/cancel" |
||||
app:layout_constraintBottom_toBottomOf="@id/btn_ok" |
||||
app:layout_constraintRight_toLeftOf="@+id/btn_ok" |
||||
app:layout_constraintTop_toTopOf="@+id/btn_ok" /> |
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout> |
@ -0,0 +1,72 @@ |
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android" |
||||
xmlns:tools="http://schemas.android.com/tools" |
||||
android:layout_width="match_parent" |
||||
android:layout_height="match_parent" |
||||
xmlns:app="http://schemas.android.com/apk/res-auto" |
||||
android:paddingLeft="20dp" |
||||
android:paddingRight="20dp" |
||||
android:paddingTop="12dp" |
||||
android:overScrollMode="ifContentScrolls"> |
||||
|
||||
<LinearLayout |
||||
android:layout_width="match_parent" |
||||
android:layout_height="wrap_content" |
||||
android:orientation="vertical"> |
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout |
||||
android:layout_width="match_parent" |
||||
android:layout_height="wrap_content" |
||||
android:paddingTop="6dp" |
||||
android:paddingBottom="6dp"> |
||||
|
||||
<TextView |
||||
android:id="@+id/tv_add_group_title" |
||||
android:layout_width="0dp" |
||||
android:layout_height="wrap_content" |
||||
android:text="@string/add_group" |
||||
android:textColor="@color/primaryText" |
||||
app:layout_constraintTop_toTopOf="parent" |
||||
app:layout_constraintLeft_toLeftOf="parent" |
||||
app:layout_constraintRight_toLeftOf="@+id/sw_add_group" /> |
||||
|
||||
<TextView |
||||
android:id="@+id/tv_add_group_s" |
||||
android:layout_width="0dp" |
||||
android:layout_height="wrap_content" |
||||
android:text="@string/custom_group_summary" |
||||
android:textColor="@color/secondaryText" |
||||
app:layout_constraintTop_toBottomOf="@+id/tv_add_group_title" |
||||
app:layout_constraintLeft_toLeftOf="parent" |
||||
app:layout_constraintRight_toLeftOf="@+id/sw_add_group" /> |
||||
|
||||
<io.legado.app.lib.theme.view.ATESwitch |
||||
android:id="@+id/sw_add_group" |
||||
android:layout_width="wrap_content" |
||||
android:layout_height="wrap_content" |
||||
android:textOff="@string/replace" |
||||
android:textOn="@string/add" |
||||
app:layout_constraintBottom_toBottomOf="parent" |
||||
app:layout_constraintRight_toRightOf="parent" |
||||
app:layout_constraintTop_toTopOf="parent" |
||||
tools:ignore="SpeakableTextPresentCheck" /> |
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout> |
||||
|
||||
<io.legado.app.ui.widget.text.TextInputLayout |
||||
android:id="@+id/text_input_layout" |
||||
android:layout_width="match_parent" |
||||
android:layout_height="wrap_content" |
||||
android:paddingTop="6dp"> |
||||
|
||||
<io.legado.app.ui.widget.text.AutoCompleteTextView |
||||
android:id="@+id/edit_view" |
||||
android:layout_width="match_parent" |
||||
android:layout_height="wrap_content" |
||||
tools:ignore="SpeakableTextPresentCheck,TouchTargetSizeCheck" /> |
||||
|
||||
</io.legado.app.ui.widget.text.TextInputLayout> |
||||
|
||||
</LinearLayout> |
||||
|
||||
</androidx.core.widget.NestedScrollView> |
@ -0,0 +1,18 @@ |
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<menu xmlns:tools="http://schemas.android.com/tools" |
||||
xmlns:android="http://schemas.android.com/apk/res/android" |
||||
xmlns:app="http://schemas.android.com/apk/res-auto"> |
||||
|
||||
<item |
||||
android:id="@+id/menu_new_group" |
||||
android:title="@string/diy_source_group" |
||||
app:showAsAction="always" |
||||
tools:ignore="AlwaysShowAction" /> |
||||
|
||||
<item |
||||
android:id="@+id/menu_Keep_original_name" |
||||
android:title="@string/keep_original_name" |
||||
android:checkable="true" |
||||
app:showAsAction="never" /> |
||||
|
||||
</menu> |
Loading…
Reference in new issue