#1627 Import export opml WIP

This commit is contained in:
sictiru 2022-03-31 21:23:52 -07:00
parent 157cf81af6
commit c45a6ae346
11 changed files with 182 additions and 1 deletions

View file

@ -70,6 +70,7 @@
android:name=".activity.Settings"
android:label="@string/settings"/>
<activity android:name=".activity.ImportExportActivity" />
<activity
android:name=".activity.WidgetConfig"
android:launchMode="singleTask"

View file

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="#383838"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M19.35,10.04C18.67,6.59 15.64,4 12,4 9.11,4 6.6,5.64 5.35,8.04 2.34,8.36 0,10.91 0,14c0,3.31 2.69,6 6,6h13c2.76,0 5,-2.24 5,-5 0,-2.64 -2.05,-4.78 -4.65,-4.96zM17,13l-5,5 -5,-5h3V9h4v4h3z" />
</vector>

View file

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="#383838"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M19.35,10.04C18.67,6.59 15.64,4 12,4 9.11,4 6.6,5.64 5.35,8.04 2.34,8.36 0,10.91 0,14c0,3.31 2.69,6 6,6h13c2.76,0 5,-2.24 5,-5 0,-2.64 -2.05,-4.78 -4.65,-4.96zM14,13v4h-4v-4H7l5,-5 5,5h-3z" />
</vector>

View file

@ -0,0 +1,43 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include layout="@layout/toolbar_newsblur" />
<androidx.appcompat.widget.AppCompatImageButton
android:id="@+id/btn_upload"
android:layout_width="80dp"
android:layout_height="80dp"
android:layout_gravity="center_horizontal"
android:layout_marginTop="64dp"
android:scaleType="fitCenter"
android:src="@drawable/ic_cloud_upload" />
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="8dp"
android:text="Import OPML"
android:textSize="18sp" />
<androidx.appcompat.widget.AppCompatImageButton
android:id="@+id/btn_download"
android:layout_width="80dp"
android:layout_height="80dp"
android:layout_gravity="center_horizontal"
android:layout_marginTop="128dp"
android:scaleType="fitCenter"
android:src="@drawable/ic_cloud_download" />
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="8dp"
android:text="Export OPML"
android:textSize="18sp" />
</LinearLayout>

View file

@ -18,6 +18,10 @@
android:title="@string/menu_premium_account"
app:showAsAction="never" />
<item android:id="@+id/menu_import_export"
android:title="@string/import_export"
app:showAsAction="never" />
<item android:id="@+id/menu_textsize"
app:showAsAction="never"
android:title="@string/menu_textsize"/>

View file

@ -268,13 +268,16 @@
<string name="feed_subscribers">%s subscribers</string>
<string name="feed_opens">%d opens</string>
<string name="feed_stories_per_month">%d stories/month</string>
<string name="import_export">Import/Export…</string>
<string name="settings">Preferences…</string>
<string name="mute_sites">Mute Sites…</string>
<string name="widget">Widget…</string>
<string name="title_widget_setup">Tap to setup in NewsBlur</string>
<string name="title_no_subscriptions">No active subscriptions detected</string>
<string name="title_widget_loading">Loading…</string>
<string name="import_export_title">Import/Export OPML</string>
<string name="premium_subscribers_folder">Reading by folder is only available to</string>
<string name="premium_subscribers_search">Search is only available to</string>

View file

@ -0,0 +1,82 @@
package com.newsblur.activity
import android.app.Activity
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.webkit.MimeTypeMap
import com.newsblur.R
import com.newsblur.databinding.ActivityImportExportBinding
import com.newsblur.network.APIConstants
import com.newsblur.util.UIUtils
import java.io.BufferedReader
import java.io.IOException
import java.io.InputStreamReader
class ImportExportActivity : NbActivity() {
private val pickXmlFileRequestCode = 10
private lateinit var binding: ActivityImportExportBinding
override fun onCreate(bundle: Bundle?) {
super.onCreate(bundle)
binding = ActivityImportExportBinding.inflate(layoutInflater)
setContentView(binding.root)
setupUI()
setupListeners()
}
private fun setupUI() {
UIUtils.setupToolbar(this, R.drawable.logo, getString(R.string.import_export_title), true)
}
private fun setupListeners() {
binding.btnUpload.setOnClickListener { pickOpmlFile() }
binding.btnDownload.setOnClickListener { exportOpmlFile() }
}
private fun pickOpmlFile() {
val mineType = MimeTypeMap.getSingleton().getMimeTypeFromExtension("xml")
Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
addCategory(Intent.CATEGORY_OPENABLE)
type = mineType
}.also {
startActivityForResult(it, pickXmlFileRequestCode)
}
}
private fun exportOpmlFile() {
val exportOpmlUrl = APIConstants.buildUrl(APIConstants.PATH_EXPORT_OPML)
UIUtils.handleUri(this, Uri.parse(exportOpmlUrl))
}
override fun onActivityResult(requestCode: Int, resultCode: Int, resultData: Intent?) {
super.onActivityResult(requestCode, resultCode, resultData)
if (requestCode == pickXmlFileRequestCode && resultCode == Activity.RESULT_OK) {
// The result data contains a URI for the document or directory that
// the user selected.
resultData?.data?.also { uri ->
// Perform operations on the document using its URI.
readTextFromUri(uri)
}
}
}
@Throws(IOException::class)
private fun readTextFromUri(uri: Uri): String {
val stringBuilder = StringBuilder()
contentResolver.openInputStream(uri)?.use { inputStream ->
BufferedReader(InputStreamReader(inputStream)).use { reader ->
var line: String? = reader.readLine()
while (line != null) {
stringBuilder.append(line)
line = reader.readLine()
}
}
}
return stringBuilder.toString()
}
}

View file

@ -347,6 +347,10 @@ public class Main extends NbActivity implements StateChangedListener, SwipeRefre
Intent intent = new Intent(this, MuteConfig.class);
startActivity(intent);
return true;
} else if (item.getItemId() == R.id.menu_import_export) {
Intent intent = new Intent(this, ImportExportActivity.class);
startActivity(intent);
return true;
}
return false;
}

View file

@ -85,6 +85,7 @@ public class APIConstants {
public static final String PATH_SAVE_RECEIPT = "/profile/save_android_receipt";
public static final String PATH_FEED_STATISTICS = "/rss_feeds/statistics_embedded/";
public static final String PATH_FEED_FAVICON_URL = "/rss_feeds/icon/";
public static final String PATH_EXPORT_OPML = "/import/opml_export";
public static String buildUrl(String path) {
return CurrentUrlBase + path;
@ -116,6 +117,7 @@ public class APIConstants {
public static final String PARAMETER_MARKSOCIAL_JSON = "users_feeds_stories";
public static final String PARAMETER_URL = "url";
public static final String PARAMETER_DAYS = "days";
public static final String PARAMETER_DATA = "data";
public static final String PARAMETER_UPDATE_COUNTS = "update_counts";
public static final String PARAMETER_CUTOFF_TIME = "cutoff_timestamp";
public static final String PARAMETER_DIRECTION = "direction";

View file

@ -196,6 +196,13 @@ public class APIManager {
return response.getResponse(gson, NewsBlurResponse.class);
}
public NewsBlurResponse importOpmlData(String data) {
final ValueMultimap values = new ValueMultimap();
values.put(APIConstants.PARAMETER_DATA, data);
APIResponse response = post(buildUrl(APIConstants.PATH_EXPORT_OPML), values);
return response.getResponse(gson, NewsBlurResponse.class);
}
public RegisterResponse signup(final String username, final String password, final String email) {
final ContentValues values = new ContentValues();
values.put(APIConstants.PARAMETER_USERNAME, username);

View file

@ -0,0 +1,15 @@
package com.newsblur.viewModel
import androidx.lifecycle.ViewModel
import com.newsblur.network.APIManager
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject
@HiltViewModel
class ImportExportViewModel
@Inject constructor(apiManager: APIManager) : ViewModel() {
fun import() {
}
}