mirror of
https://github.com/KokaKiwi/BarInsta
synced 2024-11-16 11:47:29 +00:00
Merge remote-tracking branch 'origin/task/update-feed-view' into task/update-feed-view
This commit is contained in:
commit
ded09ab237
148
.all-contributorsrc
Normal file
148
.all-contributorsrc
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
{
|
||||||
|
"files": [
|
||||||
|
"README.md"
|
||||||
|
],
|
||||||
|
"imageSize": 100,
|
||||||
|
"commit": false,
|
||||||
|
"contributors": [
|
||||||
|
{
|
||||||
|
"login": "austinhuang0131",
|
||||||
|
"name": "Austin Huang",
|
||||||
|
"avatar_url": "https://avatars1.githubusercontent.com/u/16656689",
|
||||||
|
"profile": "https://austinhuang.me",
|
||||||
|
"contributions": [
|
||||||
|
"code",
|
||||||
|
"doc",
|
||||||
|
"question",
|
||||||
|
"translation",
|
||||||
|
"ideas"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "ammargitham",
|
||||||
|
"name": "Ammar Githam",
|
||||||
|
"avatar_url": "https://avatars0.githubusercontent.com/u/8017365",
|
||||||
|
"profile": "https://github.com/ammargitham",
|
||||||
|
"contributions": [
|
||||||
|
"code",
|
||||||
|
"design",
|
||||||
|
"ideas",
|
||||||
|
"maintenance",
|
||||||
|
"question"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "AwaisKing",
|
||||||
|
"name": "AWAiS",
|
||||||
|
"avatar_url": "https://avatars3.githubusercontent.com/u/5278488",
|
||||||
|
"profile": "http://rerolledgeek.blogspot.com/",
|
||||||
|
"contributions": [
|
||||||
|
"code",
|
||||||
|
"ideas"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "Shadowspear123",
|
||||||
|
"name": "Shadowspear123",
|
||||||
|
"avatar_url": "https://avatars1.githubusercontent.com/u/50462281",
|
||||||
|
"profile": "https://github.com/Shadowspear123",
|
||||||
|
"contributions": [
|
||||||
|
"blog",
|
||||||
|
"bug",
|
||||||
|
"ideas",
|
||||||
|
"question",
|
||||||
|
"userTesting"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "KevinNThomas",
|
||||||
|
"name": "Kevin Thomas",
|
||||||
|
"avatar_url": "https://avatars2.githubusercontent.com/u/15370181",
|
||||||
|
"profile": "http://kevinthomas.dev",
|
||||||
|
"contributions": [
|
||||||
|
"financial"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "e-edgren",
|
||||||
|
"name": "Airikr",
|
||||||
|
"avatar_url": "https://avatars0.githubusercontent.com/u/53869451",
|
||||||
|
"profile": "https://airikr.me/",
|
||||||
|
"contributions": [
|
||||||
|
"question",
|
||||||
|
"ideas"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "Galang23",
|
||||||
|
"name": "Galang23",
|
||||||
|
"avatar_url": "https://avatars3.githubusercontent.com/u/13700948",
|
||||||
|
"profile": "https://github.com/Galang23",
|
||||||
|
"contributions": [
|
||||||
|
"question",
|
||||||
|
"translation"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "kernoeb",
|
||||||
|
"name": "kernoeb",
|
||||||
|
"avatar_url": "https://avatars3.githubusercontent.com/u/24623168",
|
||||||
|
"profile": "https://becauseofprog.fr/",
|
||||||
|
"contributions": [
|
||||||
|
"translation"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "Lego8486",
|
||||||
|
"name": "Ten_Lego",
|
||||||
|
"avatar_url": "https://avatars1.githubusercontent.com/u/47414485",
|
||||||
|
"profile": "https://github.com/Lego8486",
|
||||||
|
"contributions": [
|
||||||
|
"translation"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "MoaufmKlo",
|
||||||
|
"name": "MoaufmKlo",
|
||||||
|
"avatar_url": "https://avatars1.githubusercontent.com/u/45636897",
|
||||||
|
"profile": "https://github.com/MoaufmKlo",
|
||||||
|
"contributions": [
|
||||||
|
"translation"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "peterge1998",
|
||||||
|
"name": "peterge1998",
|
||||||
|
"avatar_url": "https://avatars2.githubusercontent.com/u/47355238",
|
||||||
|
"profile": "https://github.com/peterge1998",
|
||||||
|
"contributions": [
|
||||||
|
"translation"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "RAMAR-RAR",
|
||||||
|
"name": "RAMAR-RAR",
|
||||||
|
"avatar_url": "https://avatars3.githubusercontent.com/u/47423745",
|
||||||
|
"profile": "https://github.com/RAMAR-RAR",
|
||||||
|
"contributions": [
|
||||||
|
"translation"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "wagnim",
|
||||||
|
"name": "wagnim",
|
||||||
|
"avatar_url": "https://avatars0.githubusercontent.com/u/30241419",
|
||||||
|
"profile": "https://github.com/wagnim",
|
||||||
|
"contributions": [
|
||||||
|
"translation"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"contributorsPerLine": 6,
|
||||||
|
"projectName": "instagrabber",
|
||||||
|
"projectOwner": "austinhuang0131",
|
||||||
|
"repoType": "github",
|
||||||
|
"repoHost": "https://github.com",
|
||||||
|
"skipCi": true,
|
||||||
|
"commitConvention": "none"
|
||||||
|
}
|
@ -1,3 +0,0 @@
|
|||||||
component_depth: 7
|
|
||||||
languages:
|
|
||||||
- java
|
|
73
.github/CONTRIBUTING.md
vendored
Normal file
73
.github/CONTRIBUTING.md
vendored
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
## WARNING
|
||||||
|
|
||||||
|
* All forks must respect [GPLv3](https://www.gnu.org/licenses/gpl-3.0.html). Please report violations in Issues or [confidentially](https://austinhuang.me/#hey-you-look-cool).
|
||||||
|
* Although publishing a fork is allowed by license, it is strongly discouraged to do so as it divides the effort and creates confusion. It is, therefore, recommended to send a pull request back to us, so that the larger community can enjoy your improvement. (This does not apply if you're adapting this app for a different platform other than Instagram.)
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
Thank you for your interest in InstaGrabber!
|
||||||
|
|
||||||
|
Our vision of InstaGrabber is an open source true alternative of the official Instagram app. It is Austin's pursuit of a libre life that lead him to this app during its abandonment, and it was one unresolved bug that made him have the enthusiasm in implementing numerous features for this app, despite having 0 knowledge of Java beforehand.
|
||||||
|
|
||||||
|
As we grow in popularity, it becomes apparent that we are short on hands. Every contribution counts!
|
||||||
|
|
||||||
|
## I want to help coding it!
|
||||||
|
|
||||||
|
Great!
|
||||||
|
|
||||||
|
Generally, we want to imitate features in the actual Instagram app. There are many Instagram private API repositories on GitHub for you to refer to. Note that you should minimize POST: If a job should be done with GET, then there has to be a GET endpoint. (Indeed, sometimes you need multiple repositories for reference.)
|
||||||
|
|
||||||
|
As long as you have tested your version (please indicate device and API version) and make sure it works, then you can submit a PR! Large UI changes have to be voted on by the community, so it would be helpful to upload some screenshots.
|
||||||
|
|
||||||
|
Check errors are for reference only. Try to minimize them, but usually they don't make a big difference.
|
||||||
|
|
||||||
|
**NEVER touch the l10n-master branch.** It's automatically managed by Crowdin.
|
||||||
|
|
||||||
|
### Structure
|
||||||
|
|
||||||
|
It is preferred that you read the scripts yourself, as my understanding (and presentation) may be basic.
|
||||||
|
|
||||||
|
* `awais.instagrabber`
|
||||||
|
* `activities`: Scripts directly binding to each view. Assigns `adapters`.
|
||||||
|
* `adapters`: Scripts used to present a list of `models` from `asyncs` into `activities`.
|
||||||
|
* Those inside `viewholder` are for frontend, while others are for backend.
|
||||||
|
* `asyncs`: Scripts used to communicate with Instagram. Returns `models` which is sent to `adapters`.
|
||||||
|
* `asyncs.i`: Scripts that fetch data from `i.instagram.com`, except DM.
|
||||||
|
* `asyncs.direct_messages`: As the name suggests, communication scripts used for DM.
|
||||||
|
* `customviews`: Custom frontend components for this app.
|
||||||
|
* `dialogs`: Scripts directly binding to dialogs (i.e. those that are nested in the main view).
|
||||||
|
* `fragments.directmessages`: Scripts directly binding to each fragment ("small views") within `DirectMessageActivity` in `activities`.
|
||||||
|
* `interfaces`: Custom backend components for this app.
|
||||||
|
* `models`: Data structure for Instagram API responses from `asyncs`.
|
||||||
|
* `utils`: Various tools.
|
||||||
|
* `MainHelper.java` is basically an extension of `activities.main`.
|
||||||
|
* `awaisomereport`: Crash reporter. Shouldn not require too much maintenance.
|
||||||
|
* `thoughtbot.expandableadapter`: These are for the follower comparison view, which allows grouping users.
|
||||||
|
|
||||||
|
### I can't code Java, but I want to!
|
||||||
|
|
||||||
|
Fun fact: Austin took over this project and learned Java on the fly (I'm not joking, I only do JavaScript before taking this over).
|
||||||
|
|
||||||
|
Even though Java is quite annoying, it is still possible to learn it by trying to understand what these code do (Easier if you have coding experience in other languages).
|
||||||
|
|
||||||
|
If you have questions, don't be afraid to ask for help from any current maintainer!
|
||||||
|
|
||||||
|
## I found a bug!
|
||||||
|
|
||||||
|
**Please read [FAQ](https://instagrabber.austinhuang.me/faq) first.**
|
||||||
|
|
||||||
|
Bugs are inevitable during active development, as nobody can cover all the possible test cases.
|
||||||
|
|
||||||
|
You can either email your crash dump to `instagrabber@austinhuang.me` (The crash reporter will fill in this address for you) or create a GitHub issue. If you're on GitHub, please follow the template. If you're reporting by email, your email address will be published in the GitHub issue. You can contact me [privately](https://austinhuang.me/#hey-you-look-cool) or [through support channels](https://instagrabber.austinhuang.me/#what-can-i-do) to remove it.
|
||||||
|
|
||||||
|
Generally, reporting bugs directly in support channels is not recommended, as they can be difficult to find.
|
||||||
|
|
||||||
|
### I want to help... in some other way.
|
||||||
|
|
||||||
|
You can...
|
||||||
|
|
||||||
|
* translate it [![badge](https://badges.crowdin.net/instagrabber/localized.svg)](https://crowdin.com/project/instagrabber)
|
||||||
|
* promote it (reddit [r/AndroidApps](https://www.reddit.com/r/androidapps/comments/i30tpp/instagrabber_an_open_source_instagram_client/), YouTube [HowToMen](https://www.youtube.com/watch?v=1Um2ZJG_mB4), [Ekşi Sözlük](https://eksisozluk.com/instagrabber--6643143))
|
||||||
|
* star it [![stars](https://img.shields.io/github/stars/austinhuang0131/instagrabber.svg?style=social&label=Star)](https://github.com/austinhuang0131/instagrabber/stargazers)
|
||||||
|
|
||||||
|
Happy contributing!
|
14
.github/ISSUE_TEMPLATE/bug_report.md
vendored
14
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@ -4,31 +4,27 @@ about: App crashing? You seeing a confusing error message? Report them here!
|
|||||||
title: "[BUG]"
|
title: "[BUG]"
|
||||||
labels: bug
|
labels: bug
|
||||||
assignees: ''
|
assignees: ''
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
<!-- FOLLOW THIS FORMAT -->
|
||||||
|
|
||||||
- [ ] My app is on the latest version. I understand that any other version is not supported.
|
- [ ] My app is on the latest version. I understand that any other version is not supported.
|
||||||
|
- [ ] I have read [the FAQ](https://instagrabber.austinhuang.me/faq).
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
First, describe the bug here. Don't stress too much, but do include the key points.
|
Describe the bug here. Don't stress too much, but do include the key points.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
## Steps
|
## Steps
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
DETAILED Steps to reproduce the behaviour. If you do not describe this part clearly, I may ignore the issue.
|
DETAILED Steps to reproduce the behaviour.
|
||||||
1. Go to '...'
|
1. Go to '...'
|
||||||
2. Click on '....'
|
2. Click on '....'
|
||||||
3. Scroll down to '....'
|
3. Scroll down to '....'
|
||||||
4. See error
|
4. See error
|
||||||
-->
|
-->
|
||||||
|
|
||||||
### Expected Behaviour
|
|
||||||
|
|
||||||
## Screenshots
|
|
||||||
|
|
||||||
<!-- if applicable, remove otherwise -->
|
|
||||||
|
|
||||||
## Environment
|
## Environment
|
||||||
|
|
||||||
- Device:
|
- Device:
|
||||||
|
5
.github/ISSUE_TEMPLATE/feature_request.md
vendored
5
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@ -8,9 +8,9 @@ assignees: ''
|
|||||||
---
|
---
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
The only source of Java experience for the owner is from this app
|
|
||||||
Large features will either take a lot of time or another maintainer
|
Large features will either take a lot of time or another maintainer
|
||||||
Just remember to be patient, and if you have skills, try DIY
|
Just remember to be patient, and if you have skills, try DIY
|
||||||
|
Also write title after [FTR]
|
||||||
-->
|
-->
|
||||||
|
|
||||||
**Is your feature request related to a problem? Please describe.**
|
**Is your feature request related to a problem? Please describe.**
|
||||||
@ -19,8 +19,5 @@ A clear and concise description of what the problem is. Ex. I'm always frustrate
|
|||||||
**Describe the solution you'd like**
|
**Describe the solution you'd like**
|
||||||
A clear and concise description of what you want to happen.
|
A clear and concise description of what you want to happen.
|
||||||
|
|
||||||
**Describe alternatives you've considered**
|
|
||||||
A clear and concise description of any alternative solutions or features you've considered.
|
|
||||||
|
|
||||||
**Additional context**
|
**Additional context**
|
||||||
Add any other context or screenshots about the feature request here.
|
Add any other context or screenshots about the feature request here.
|
||||||
|
73
README.md
73
README.md
@ -8,37 +8,20 @@
|
|||||||
[![GPLv3 license](https://img.shields.io/badge/License-GPLv3-blue.svg)](./LICENSE)
|
[![GPLv3 license](https://img.shields.io/badge/License-GPLv3-blue.svg)](./LICENSE)
|
||||||
[![GitHub stars](https://img.shields.io/github/stars/austinhuang0131/instagrabber.svg?style=social&label=Star)](https://GitHub.com/austinhuang0131/instagrabber/stargazers/)
|
[![GitHub stars](https://img.shields.io/github/stars/austinhuang0131/instagrabber.svg?style=social&label=Star)](https://GitHub.com/austinhuang0131/instagrabber/stargazers/)
|
||||||
|
|
||||||
*As featured on [HowToMen](https://youtu.be/1Um2ZJG_mB4) and [GitHub Trending](https://github.com/ifyour/github-trending-archive/blob/master/archives/2020-08-05.md)*
|
For documentation, visit [InstaGrabber.AustinHuang.me](https://instagrabber.austinhuang.me).
|
||||||
|
|
||||||
### Download
|
### Download
|
||||||
|
|
||||||
<a href="https://f-droid.org/en/packages/me.austinhuang.instagrabber/"><img src="https://fdroid.gitlab.io/artwork/badge/get-it-on.png" height="100"></a>
|
**By installing, you indicate your acceptance of [Disclosure and Privacy Policy](https://instagrabber.austinhuang.me/disclosure).**
|
||||||
|
|
||||||
Or you can download from [GitHub releases](https://github.com/austinhuang0131/instagrabber/releases/latest). Expand "Assets" and download the APK file.
|
Download from [GitHub releases](https://github.com/austinhuang0131/instagrabber/releases/latest) (recommended). Expand "Assets" and download the APK file. Or...
|
||||||
|
|
||||||
|
<a href="https://f-droid.org/en/packages/me.austinhuang.instagrabber/"><img src="https://fdroid.gitlab.io/artwork/badge/get-it-on.png" height="75"></a>
|
||||||
|
|
||||||
|
(...[but they're slow.](https://instagrabber.austinhuang.me/faq#f-droid))
|
||||||
|
|
||||||
Version status: ![F-Droid](https://img.shields.io/f-droid/v/me.austinhuang.instagrabber.svg) vs. ![GitHub](https://img.shields.io/github/release/austinhuang0131/instagrabber.svg?logo=github)
|
Version status: ![F-Droid](https://img.shields.io/f-droid/v/me.austinhuang.instagrabber.svg) vs. ![GitHub](https://img.shields.io/github/release/austinhuang0131/instagrabber.svg?logo=github)
|
||||||
|
|
||||||
### Presentation
|
|
||||||
|
|
||||||
InstaGrabber is an alternative Instagram client for Android. You can...
|
|
||||||
|
|
||||||
* **Search**: Profile / Hashtag / Location
|
|
||||||
* **Profile**: View posts (timeline & face-tagged), copy bio, view stories\* (Highlight & status), follow\*, restrict\*, block\*, compare following/followers\*<sup>,3</sup>
|
|
||||||
* **Hashtag**: View posts (newest only), view stories\*, follow\*
|
|
||||||
* **Location**: View posts (newest only), view stories\*, open map
|
|
||||||
* **Post**: View, download (+ batch download selected posts), copy captions, like/save\*
|
|
||||||
* **Story**: View (with [storiesig](https://storiesig.com) support<sup>1</sup> and incognito mode<sup>2</sup>), download, interact with stickers\*, reply as DM\*
|
|
||||||
* **Comment**: View (+ copy), write\*, reply\*, like\*, delete\*
|
|
||||||
* **DM\***: View, download attachments, text reply
|
|
||||||
* Viewing\* your own feed, discover, saved, and liked posts
|
|
||||||
* Adding personal bookmarks to accounts/hashtags/locations locally
|
|
||||||
|
|
||||||
We support private accounts!\*
|
|
||||||
|
|
||||||
It can be used as a drop-in replacement for read (and some write) functionalities of the official Instagram app, with unnecessary components stripped.
|
|
||||||
|
|
||||||
<sub>* Requires [login](#how-to-log-in). You must be a current follower of the desired private accounts, this app cannot hack people (which I have to state despite the obvious)!</sub>
|
|
||||||
|
|
||||||
<a href="https://github.com/austinhuang0131/instagrabber/blob/master/fastlane/metadata/android/images/en-US/phoneScreenshots/1.jpg"><img src="./fastlane/metadata/android/en-US/images/phoneScreenshots/1.jpg" alt="Profile" width="15%"/></a>
|
<a href="https://github.com/austinhuang0131/instagrabber/blob/master/fastlane/metadata/android/images/en-US/phoneScreenshots/1.jpg"><img src="./fastlane/metadata/android/en-US/images/phoneScreenshots/1.jpg" alt="Profile" width="15%"/></a>
|
||||||
<a href="https://github.com/austinhuang0131/instagrabber/blob/master/fastlane/metadata/android/images/en-US/phoneScreenshots/2.jpg"><img src="./fastlane/metadata/android/en-US/images/phoneScreenshots/2.jpg" alt="Post" width="15%"/></a>
|
<a href="https://github.com/austinhuang0131/instagrabber/blob/master/fastlane/metadata/android/images/en-US/phoneScreenshots/2.jpg"><img src="./fastlane/metadata/android/en-US/images/phoneScreenshots/2.jpg" alt="Post" width="15%"/></a>
|
||||||
<a href="https://github.com/austinhuang0131/instagrabber/blob/master/fastlane/metadata/android/images/en-US/phoneScreenshots/3.jpg"><img src="./fastlane/metadata/android/en-US/images/phoneScreenshots/3.jpg" alt="Comments" width="15%"/></a>
|
<a href="https://github.com/austinhuang0131/instagrabber/blob/master/fastlane/metadata/android/images/en-US/phoneScreenshots/3.jpg"><img src="./fastlane/metadata/android/en-US/images/phoneScreenshots/3.jpg" alt="Comments" width="15%"/></a>
|
||||||
@ -54,6 +37,43 @@ It can be used as a drop-in replacement for read (and some write) functionalitie
|
|||||||
* Telegram: [@Grabber_App](https://t.me/grabber_app)
|
* Telegram: [@Grabber_App](https://t.me/grabber_app)
|
||||||
* Discord: [https://discord.gg/YtEDzN2](https://discord.gg/YtEDzN2)
|
* Discord: [https://discord.gg/YtEDzN2](https://discord.gg/YtEDzN2)
|
||||||
|
|
||||||
|
### Contributors
|
||||||
|
|
||||||
|
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
|
||||||
|
[![All Contributors](https://img.shields.io/badge/all_contributors-13-orange.svg?style=flat-square)](#contributors-)
|
||||||
|
<!-- ALL-CONTRIBUTORS-BADGE:END -->
|
||||||
|
|
||||||
|
Prominent contributors are listed here in the [all-contributors](https://allcontributors.org/) specifications. See [emoji key](https://allcontributors.org/docs/en/emoji-key).
|
||||||
|
|
||||||
|
<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
|
||||||
|
<!-- prettier-ignore-start -->
|
||||||
|
<!-- markdownlint-disable -->
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<td align="center"><a href="https://austinhuang.me"><img src="https://avatars1.githubusercontent.com/u/16656689?s=100" width="100px;" alt=""/><br /><sub><b>Austin Huang</b></sub></a><br /><a href="https://github.com/austinhuang0131/instagrabber/commits?author=austinhuang0131" title="Code">💻</a> <a href="https://github.com/austinhuang0131/instagrabber/commits?author=austinhuang0131" title="Documentation">📖</a> <a href="#question-austinhuang0131" title="Answering Questions">💬</a> <a href="#translation-austinhuang0131" title="Translation">🌍</a> <a href="#ideas-austinhuang0131" title="Ideas, Planning, & Feedback">🤔</a></td>
|
||||||
|
<td align="center"><a href="https://github.com/ammargitham"><img src="https://avatars0.githubusercontent.com/u/8017365?s=100" width="100px;" alt=""/><br /><sub><b>Ammar Githam</b></sub></a><br /><a href="https://github.com/austinhuang0131/instagrabber/commits?author=ammargitham" title="Code">💻</a> <a href="#design-ammargitham" title="Design">🎨</a> <a href="#ideas-ammargitham" title="Ideas, Planning, & Feedback">🤔</a> <a href="#maintenance-ammargitham" title="Maintenance">🚧</a> <a href="#question-ammargitham" title="Answering Questions">💬</a></td>
|
||||||
|
<td align="center"><a href="http://rerolledgeek.blogspot.com/"><img src="https://avatars3.githubusercontent.com/u/5278488?s=100" width="100px;" alt=""/><br /><sub><b>AWAiS</b></sub></a><br /><a href="https://github.com/austinhuang0131/instagrabber/commits?author=AwaisKing" title="Code">💻</a> <a href="#ideas-AwaisKing" title="Ideas, Planning, & Feedback">🤔</a></td>
|
||||||
|
<td align="center"><a href="https://github.com/Shadowspear123"><img src="https://avatars1.githubusercontent.com/u/50462281?s=100" width="100px;" alt=""/><br /><sub><b>Shadowspear123</b></sub></a><br /><a href="#blog-Shadowspear123" title="Blogposts">📝</a> <a href="https://github.com/austinhuang0131/instagrabber/issues?q=author%3AShadowspear123" title="Bug reports">🐛</a> <a href="#ideas-Shadowspear123" title="Ideas, Planning, & Feedback">🤔</a> <a href="#question-Shadowspear123" title="Answering Questions">💬</a> <a href="#userTesting-Shadowspear123" title="User Testing">📓</a></td>
|
||||||
|
<td align="center"><a href="http://kevinthomas.dev"><img src="https://avatars2.githubusercontent.com/u/15370181?s=100" width="100px;" alt=""/><br /><sub><b>Kevin Thomas</b></sub></a><br /><a href="#financial-KevinNThomas" title="Financial">💵</a></td>
|
||||||
|
<td align="center"><a href="https://airikr.me/"><img src="https://avatars0.githubusercontent.com/u/53869451?s=100" width="100px;" alt=""/><br /><sub><b>Airikr</b></sub></a><br /><a href="#question-e-edgren" title="Answering Questions">💬</a> <a href="#ideas-e-edgren" title="Ideas, Planning, & Feedback">🤔</a></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td align="center"><a href="https://github.com/Galang23"><img src="https://avatars3.githubusercontent.com/u/13700948?s=100" width="100px;" alt=""/><br /><sub><b>Galang23</b></sub></a><br /><a href="#question-Galang23" title="Answering Questions">💬</a> <a href="#translation-Galang23" title="Translation">🌍</a></td>
|
||||||
|
<td align="center"><a href="https://becauseofprog.fr/"><img src="https://avatars3.githubusercontent.com/u/24623168?s=100" width="100px;" alt=""/><br /><sub><b>kernoeb</b></sub></a><br /><a href="#translation-kernoeb" title="Translation">🌍</a></td>
|
||||||
|
<td align="center"><a href="https://github.com/Lego8486"><img src="https://avatars1.githubusercontent.com/u/47414485?s=100" width="100px;" alt=""/><br /><sub><b>Ten_Lego</b></sub></a><br /><a href="#translation-Lego8486" title="Translation">🌍</a></td>
|
||||||
|
<td align="center"><a href="https://github.com/MoaufmKlo"><img src="https://avatars1.githubusercontent.com/u/45636897?s=100" width="100px;" alt=""/><br /><sub><b>MoaufmKlo</b></sub></a><br /><a href="#translation-MoaufmKlo" title="Translation">🌍</a></td>
|
||||||
|
<td align="center"><a href="https://github.com/peterge1998"><img src="https://avatars2.githubusercontent.com/u/47355238?s=100" width="100px;" alt=""/><br /><sub><b>peterge1998</b></sub></a><br /><a href="#translation-peterge1998" title="Translation">🌍</a></td>
|
||||||
|
<td align="center"><a href="https://github.com/RAMAR-RAR"><img src="https://avatars3.githubusercontent.com/u/47423745?s=100" width="100px;" alt=""/><br /><sub><b>RAMAR-RAR</b></sub></a><br /><a href="#translation-RAMAR-RAR" title="Translation">🌍</a></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td align="center"><a href="https://github.com/wagnim"><img src="https://avatars0.githubusercontent.com/u/30241419?s=100" width="100px;" alt=""/><br /><sub><b>wagnim</b></sub></a><br /><a href="#translation-wagnim" title="Translation">🌍</a></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<!-- markdownlint-restore -->
|
||||||
|
<!-- prettier-ignore-end -->
|
||||||
|
<!-- ALL-CONTRIBUTORS-LIST:END -->
|
||||||
|
|
||||||
### License
|
### License
|
||||||
|
|
||||||
This app is originally made by [@AwaisKing](https://github.com/AwaisKing) on [GitLab](https://gitlab.com/AwaisKing/instagrabber).
|
This app is originally made by [@AwaisKing](https://github.com/AwaisKing) on [GitLab](https://gitlab.com/AwaisKing/instagrabber).
|
||||||
@ -79,9 +99,8 @@ This app is originally made by [@AwaisKing](https://github.com/AwaisKing) on [Gi
|
|||||||
[![Snyk Vulnerabilities](https://img.shields.io/snyk/vulnerabilities/github/austinhuang0131/instagrabber)](https://snyk.io/test/github/austinhuang0131/instagrabber)
|
[![Snyk Vulnerabilities](https://img.shields.io/snyk/vulnerabilities/github/austinhuang0131/instagrabber)](https://snyk.io/test/github/austinhuang0131/instagrabber)
|
||||||
[![LGTM Alerts](https://img.shields.io/lgtm/alerts/github/austinhuang0131/instagrabber)](https://lgtm.com/projects/g/austinhuang0131/instagrabber)
|
[![LGTM Alerts](https://img.shields.io/lgtm/alerts/github/austinhuang0131/instagrabber)](https://lgtm.com/projects/g/austinhuang0131/instagrabber)
|
||||||
[![LGTM Grade](https://img.shields.io/lgtm/grade/java/github/austinhuang0131/instagrabber)](https://lgtm.com/projects/g/austinhuang0131/instagrabber)
|
[![LGTM Grade](https://img.shields.io/lgtm/grade/java/github/austinhuang0131/instagrabber)](https://lgtm.com/projects/g/austinhuang0131/instagrabber)
|
||||||
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/f87cac1fbf674888b00bd91bc5eccce0)](https://app.codacy.com/manual/austinhuang0131/instagrabber)
|
[![CodeFactor](https://www.codefactor.io/repository/github/austinhuang0131/instagrabber/badge)](https://www.codefactor.io/repository/github/austinhuang0131/instagrabber)
|
||||||
|
[![Codacy Badge](https://app.codacy.com/project/badge/Grade/e9cfcb7733f8477d92e5c0f30cac137a)](https://www.codacy.com/manual/austinhuang0131/instagrabber)
|
||||||
[![Crowdin](https://badges.crowdin.net/instagrabber/localized.svg)](https://crowdin.com/project/instagrabber)
|
[![Crowdin](https://badges.crowdin.net/instagrabber/localized.svg)](https://crowdin.com/project/instagrabber)
|
||||||
|
|
||||||
[![forthebadge](https://forthebadge.com/images/badges/made-with-java.svg)](https://forthebadge.com)[![forthebadge](https://forthebadge.com/images/badges/built-for-android.svg)](https://forthebadge.com) [![gplv3](https://www.gnu.org/graphics/gplv3-with-text-136x68.png)](https://www.gnu.org/licenses/gpl-3.0.html)
|
[![forthebadge](https://forthebadge.com/images/badges/made-with-java.svg)](https://forthebadge.com)[![forthebadge](https://forthebadge.com/images/badges/built-for-android.svg)](https://forthebadge.com) [![gplv3](https://www.gnu.org/graphics/gplv3-with-text-136x68.png)](https://www.gnu.org/licenses/gpl-3.0.html)
|
||||||
|
|
||||||
<sub>1. For anonymous users only, does not apply to users already logged in, and must be explicitly enabled in Settings. 2. Default enabled, but can be disabled. 3. Shameless plug: If you do not have an Android device but wants to do that, read [this](https://austinhuang.me/instagram-compare).</sub>
|
|
||||||
|
@ -119,21 +119,25 @@ public final class CommentsViewer extends BaseLanguageActivity implements SwipeR
|
|||||||
} else if (which == 3) {
|
} else if (which == 3) {
|
||||||
Utils.copyText(this, commentModel.getText().toString());
|
Utils.copyText(this, commentModel.getText().toString());
|
||||||
} else if (which == 4) {
|
} else if (which == 4) {
|
||||||
focus = commentsBinding.rvComments.findViewWithTag(commentModel);
|
if (commentModel == null) {
|
||||||
focus.setBackgroundColor(0x80888888);
|
Toast.makeText(getApplicationContext(), R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show();
|
||||||
commentsBinding.commentCancelParent.setVisibility(View.VISIBLE);
|
}
|
||||||
String mention = "@"+profileModel.getUsername()+" ";
|
else {
|
||||||
commentsBinding.commentText.setText(mention);
|
focus = commentsBinding.rvComments.findViewWithTag(commentModel);
|
||||||
commentsBinding.commentText.requestFocus();
|
focus.setBackgroundColor(0x80888888);
|
||||||
commentsBinding.commentText.setSelection(mention.length());
|
commentsBinding.commentCancelParent.setVisibility(View.VISIBLE);
|
||||||
commentsBinding.commentText.postDelayed(new Runnable(){
|
String mention = "@" + profileModel.getUsername() + " ";
|
||||||
@Override
|
commentsBinding.commentText.setText(mention);
|
||||||
public void run(){
|
commentsBinding.commentText.requestFocus();
|
||||||
imm = (InputMethodManager) getSystemService(getApplicationContext().INPUT_METHOD_SERVICE);
|
commentsBinding.commentText.setSelection(mention.length());
|
||||||
imm.showSoftInput(commentsBinding.commentText, 0);
|
commentsBinding.commentText.postDelayed(new Runnable() {
|
||||||
}
|
@Override
|
||||||
|
public void run() {
|
||||||
|
imm = (InputMethodManager) getSystemService(getApplicationContext().INPUT_METHOD_SERVICE);
|
||||||
|
imm.showSoftInput(commentsBinding.commentText, 0);
|
||||||
|
}
|
||||||
|
}, 200);
|
||||||
}
|
}
|
||||||
,200);
|
|
||||||
} else if (which == 5) {
|
} else if (which == 5) {
|
||||||
new CommentAction().execute((commentModel.getLiked() ? "unlike/" : "like/")+commentModel.getId());
|
new CommentAction().execute((commentModel.getLiked() ? "unlike/" : "like/")+commentModel.getId());
|
||||||
} else if (which == 6) {
|
} else if (which == 6) {
|
||||||
|
@ -222,11 +222,9 @@ public final class PostViewer extends BaseLanguageActivity {
|
|||||||
viewerBinding.bottomPanel.commentsCount.setText(String.valueOf(commentsCount));
|
viewerBinding.bottomPanel.commentsCount.setText(String.valueOf(commentsCount));
|
||||||
viewerBinding.bottomPanel.btnComments.setVisibility(View.VISIBLE);
|
viewerBinding.bottomPanel.btnComments.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
postShortCode = result[0].getShortCode();
|
|
||||||
|
|
||||||
viewerBinding.bottomPanel.btnComments.setOnClickListener(v ->
|
viewerBinding.bottomPanel.btnComments.setOnClickListener(v ->
|
||||||
startActivityForResult(new Intent(this, CommentsViewer.class)
|
startActivityForResult(new Intent(this, CommentsViewer.class)
|
||||||
.putExtra(Constants.EXTRAS_SHORTCODE, postShortCode)
|
.putExtra(Constants.EXTRAS_SHORTCODE, postModel.getShortCode())
|
||||||
.putExtra(Constants.EXTRAS_POST, viewerPostModel.getPostId())
|
.putExtra(Constants.EXTRAS_POST, viewerPostModel.getPostId())
|
||||||
.putExtra(Constants.EXTRAS_USER, postUserId), 6969));
|
.putExtra(Constants.EXTRAS_USER, postUserId), 6969));
|
||||||
viewerBinding.bottomPanel.btnComments.setClickable(true);
|
viewerBinding.bottomPanel.btnComments.setClickable(true);
|
||||||
@ -243,7 +241,8 @@ public final class PostViewer extends BaseLanguageActivity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setupPostInfoBar("@" + viewerPostModel.getUsername(), viewerPostModel.getItemType(), viewerPostModel.getLocation());
|
setupPostInfoBar("@" + viewerPostModel.getUsername(), viewerPostModel.getItemType(),
|
||||||
|
viewerPostModel.getLocationName(), viewerPostModel.getLocation());
|
||||||
|
|
||||||
postCaption = postModel.getPostCaption();
|
postCaption = postModel.getPostCaption();
|
||||||
viewerCaptionParent.setVisibility(View.VISIBLE);
|
viewerCaptionParent.setVisibility(View.VISIBLE);
|
||||||
@ -302,7 +301,7 @@ public final class PostViewer extends BaseLanguageActivity {
|
|||||||
|
|
||||||
final boolean postIdNull = postModel.getPostId() == null;
|
final boolean postIdNull = postModel.getPostId() == null;
|
||||||
if (!postIdNull)
|
if (!postIdNull)
|
||||||
setupPostInfoBar(intent.getStringExtra(Constants.EXTRAS_USER), postModel.getItemType(), null);
|
setupPostInfoBar(intent.getStringExtra(Constants.EXTRAS_USER), postModel.getItemType(), null, null);
|
||||||
|
|
||||||
isFromShare = postModel.getPosition() == -1 || postIdNull;
|
isFromShare = postModel.getPosition() == -1 || postIdNull;
|
||||||
|
|
||||||
@ -585,7 +584,7 @@ public final class PostViewer extends BaseLanguageActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setupPostInfoBar("@" + viewerPostModel.getUsername(), viewerPostModel.getItemType(),
|
setupPostInfoBar("@" + viewerPostModel.getUsername(), viewerPostModel.getItemType(),
|
||||||
viewerPostModel.getLocation());
|
viewerPostModel.getLocationName(), viewerPostModel.getLocation());
|
||||||
|
|
||||||
if (postModel instanceof PostModel) {
|
if (postModel instanceof PostModel) {
|
||||||
final PostModel postModel = (PostModel) this.postModel;
|
final PostModel postModel = (PostModel) this.postModel;
|
||||||
@ -633,7 +632,7 @@ public final class PostViewer extends BaseLanguageActivity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setupPostInfoBar(final String from, final MediaItemType mediaItemType, final JSONObject location) {
|
private void setupPostInfoBar(final String from, final MediaItemType mediaItemType, final String locationName, final String location) {
|
||||||
if (prevUsername == null || !prevUsername.equals(from)) {
|
if (prevUsername == null || !prevUsername.equals(from)) {
|
||||||
// viewerBinding.topPanel.ivProfilePic.setImageBitmap(null);
|
// viewerBinding.topPanel.ivProfilePic.setImageBitmap(null);
|
||||||
// viewerBinding.topPanel.ivProfilePic.setImageDrawable(null);
|
// viewerBinding.topPanel.ivProfilePic.setImageDrawable(null);
|
||||||
@ -708,8 +707,8 @@ public final class PostViewer extends BaseLanguageActivity {
|
|||||||
));
|
));
|
||||||
} else {
|
} else {
|
||||||
viewerBinding.topPanel.location.setVisibility(View.VISIBLE);
|
viewerBinding.topPanel.location.setVisibility(View.VISIBLE);
|
||||||
viewerBinding.topPanel.location.setText(location.optString("name"));
|
viewerBinding.topPanel.location.setText(locationName);
|
||||||
viewerBinding.topPanel.location.setOnClickListener(v -> searchUsername(location.optString("id") + "/" + location.optString("slug")));
|
viewerBinding.topPanel.location.setOnClickListener(v -> searchUsername(location));
|
||||||
viewerBinding.topPanel.title.setLayoutParams(new RelativeLayout.LayoutParams(
|
viewerBinding.topPanel.title.setLayoutParams(new RelativeLayout.LayoutParams(
|
||||||
RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT
|
RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT
|
||||||
));
|
));
|
||||||
|
@ -106,7 +106,8 @@ public final class DirectMessageItemsAdapter extends ListAdapter<DirectItemModel
|
|||||||
final LayoutDmRavenMediaBinding binding = LayoutDmRavenMediaBinding.inflate(layoutInflater, itemViewParent, false);
|
final LayoutDmRavenMediaBinding binding = LayoutDmRavenMediaBinding.inflate(layoutInflater, itemViewParent, false);
|
||||||
return new DirectMessageReelShareViewHolder(baseBinding, binding, onClickListener, mentionClickListener);
|
return new DirectMessageReelShareViewHolder(baseBinding, binding, onClickListener, mentionClickListener);
|
||||||
}
|
}
|
||||||
case MEDIA_SHARE: {
|
case MEDIA_SHARE:
|
||||||
|
case CLIP: {
|
||||||
final LayoutDmMediaShareBinding binding = LayoutDmMediaShareBinding.inflate(layoutInflater, itemViewParent, false);
|
final LayoutDmMediaShareBinding binding = LayoutDmMediaShareBinding.inflate(layoutInflater, itemViewParent, false);
|
||||||
return new DirectMessageMediaShareViewHolder(baseBinding, binding, onClickListener);
|
return new DirectMessageMediaShareViewHolder(baseBinding, binding, onClickListener);
|
||||||
}
|
}
|
||||||
|
@ -71,6 +71,7 @@ public final class DirectMessageInboxItemViewHolder extends RecyclerView.ViewHol
|
|||||||
case MEDIA:
|
case MEDIA:
|
||||||
case MEDIA_SHARE:
|
case MEDIA_SHARE:
|
||||||
case RAVEN_MEDIA:
|
case RAVEN_MEDIA:
|
||||||
|
case CLIP:
|
||||||
messageText = context.getString(R.string.direct_messages_sent_media);
|
messageText = context.getString(R.string.direct_messages_sent_media);
|
||||||
break;
|
break;
|
||||||
case ACTION_LOG:
|
case ACTION_LOG:
|
||||||
|
@ -148,7 +148,7 @@ public final class CommentsFetcher extends AsyncTask<Void, Void, CommentModel[]>
|
|||||||
|
|
||||||
String endCursor = "";
|
String endCursor = "";
|
||||||
while (endCursor != null) {
|
while (endCursor != null) {
|
||||||
final String url = "https://www.instagram.com/graphql/query/?query_hash=97b41c52301f77ce508f55e66d17620e&variables=" +
|
final String url = "https://www.instagram.com/graphql/query/?query_hash=bc3296d1ce80a24b1b6e40b1e72903f5&variables=" +
|
||||||
"{\"shortcode\":\"" + shortCode + "\",\"first\":50,\"after\":\"" + endCursor + "\"}";
|
"{\"shortcode\":\"" + shortCode + "\",\"first\":50,\"after\":\"" + endCursor + "\"}";
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -164,7 +164,10 @@ public final class FeedFetcher extends AsyncTask<Void, Void, FeedModel[]> {
|
|||||||
null, null, null,
|
null, null, null,
|
||||||
node.optLong("video_view_count", -1), -1, false, false,
|
node.optLong("video_view_count", -1), -1, false, false,
|
||||||
feedItem.getJSONObject("edge_media_preview_like").getLong("count"),
|
feedItem.getJSONObject("edge_media_preview_like").getLong("count"),
|
||||||
feedItem.optJSONObject("location"));
|
feedItem.isNull("location") ? null : feedItem.getJSONObject("location").optString("name"),
|
||||||
|
feedItem.isNull("location") ? null :
|
||||||
|
(feedItem.getJSONObject("location").optString("id") + "/" +
|
||||||
|
feedItem.getJSONObject("location").optString("slug")));
|
||||||
|
|
||||||
sliderItems[j].setSliderDisplayUrl(node.getString("display_url"));
|
sliderItems[j].setSliderDisplayUrl(node.getString("display_url"));
|
||||||
}
|
}
|
||||||
|
@ -95,7 +95,10 @@ public final class PostFetcher extends AsyncTask<Void, Void, ViewerPostModel[]>
|
|||||||
isVideo && media.has("video_view_count") ? media.getLong("video_view_count") : -1,
|
isVideo && media.has("video_view_count") ? media.getLong("video_view_count") : -1,
|
||||||
timestamp, media.getBoolean("viewer_has_liked"), media.getBoolean("viewer_has_saved"),
|
timestamp, media.getBoolean("viewer_has_liked"), media.getBoolean("viewer_has_saved"),
|
||||||
media.getJSONObject("edge_media_preview_like").getLong("count"),
|
media.getJSONObject("edge_media_preview_like").getLong("count"),
|
||||||
media.optJSONObject("location"));
|
media.isNull("location") ? null : media.getJSONObject("location").optString("name"),
|
||||||
|
media.isNull("location") ? null :
|
||||||
|
(media.getJSONObject("location").optString("id") + "/" +
|
||||||
|
media.getJSONObject("location").optString("slug")));
|
||||||
|
|
||||||
postModel.setCommentsCount(commentsCount);
|
postModel.setCommentsCount(commentsCount);
|
||||||
|
|
||||||
@ -120,7 +123,10 @@ public final class PostFetcher extends AsyncTask<Void, Void, ViewerPostModel[]>
|
|||||||
isChildVideo && node.has("video_view_count") ? node.getLong("video_view_count") : -1,
|
isChildVideo && node.has("video_view_count") ? node.getLong("video_view_count") : -1,
|
||||||
timestamp, media.getBoolean("viewer_has_liked"), media.getBoolean("viewer_has_saved"),
|
timestamp, media.getBoolean("viewer_has_liked"), media.getBoolean("viewer_has_saved"),
|
||||||
media.getJSONObject("edge_media_preview_like").getLong("count"),
|
media.getJSONObject("edge_media_preview_like").getLong("count"),
|
||||||
media.optJSONObject("location"));
|
media.isNull("location") ? null : media.getJSONObject("location").optString("name"),
|
||||||
|
media.isNull("location") ? null :
|
||||||
|
(media.getJSONObject("location").optString("id") + "/" +
|
||||||
|
media.getJSONObject("location").optString("slug")));
|
||||||
postModels[i].setSliderDisplayUrl(node.getString("display_url"));
|
postModels[i].setSliderDisplayUrl(node.getString("display_url"));
|
||||||
|
|
||||||
Utils.checkExistence(downloadDir, customDir, true, postModels[i]);
|
Utils.checkExistence(downloadDir, customDir, true, postModels[i]);
|
||||||
|
@ -87,7 +87,10 @@ public final class iPostFetcher extends AsyncTask<Void, Void, ViewerPostModel[]>
|
|||||||
isVideo && media.has("view_count") ? media.getLong("view_count") : -1,
|
isVideo && media.has("view_count") ? media.getLong("view_count") : -1,
|
||||||
timestamp, media.optBoolean("has_liked"), media.optBoolean("has_viewer_saved"),
|
timestamp, media.optBoolean("has_liked"), media.optBoolean("has_viewer_saved"),
|
||||||
media.getLong("like_count"),
|
media.getLong("like_count"),
|
||||||
media.optJSONObject("location"));
|
media.isNull("location") ? null : media.getJSONObject("location").optString("name"),
|
||||||
|
media.isNull("location") ? null :
|
||||||
|
(media.getJSONObject("location").optString("id") + "/" +
|
||||||
|
media.getJSONObject("location").optString("slug")));
|
||||||
|
|
||||||
postModel.setCommentsCount(commentsCount);
|
postModel.setCommentsCount(commentsCount);
|
||||||
|
|
||||||
@ -114,7 +117,10 @@ public final class iPostFetcher extends AsyncTask<Void, Void, ViewerPostModel[]>
|
|||||||
-1,
|
-1,
|
||||||
timestamp, media.optBoolean("has_liked"), media.optBoolean("has_viewer_saved"),
|
timestamp, media.optBoolean("has_liked"), media.optBoolean("has_viewer_saved"),
|
||||||
media.getLong("like_count"),
|
media.getLong("like_count"),
|
||||||
media.optJSONObject("location"));
|
media.isNull("location") ? null : media.getJSONObject("location").optString("name"),
|
||||||
|
media.isNull("location") ? null :
|
||||||
|
(media.getJSONObject("location").optString("id") + "/" +
|
||||||
|
media.getJSONObject("location").optString("slug")));
|
||||||
postModels[i].setSliderDisplayUrl(Utils.getHighQualityImage(node));
|
postModels[i].setSliderDisplayUrl(Utils.getHighQualityImage(node));
|
||||||
|
|
||||||
Utils.checkExistence(downloadDir, customDir, true, postModels[i]);
|
Utils.checkExistence(downloadDir, customDir, true, postModels[i]);
|
||||||
|
@ -16,7 +16,9 @@ import awais.instagrabber.models.enums.MediaItemType;
|
|||||||
import awais.instagrabber.models.stickers.PollModel;
|
import awais.instagrabber.models.stickers.PollModel;
|
||||||
import awais.instagrabber.models.stickers.QuestionModel;
|
import awais.instagrabber.models.stickers.QuestionModel;
|
||||||
import awais.instagrabber.models.stickers.QuizModel;
|
import awais.instagrabber.models.stickers.QuizModel;
|
||||||
|
import awais.instagrabber.models.stickers.SwipeUpModel;
|
||||||
import awais.instagrabber.utils.Constants;
|
import awais.instagrabber.utils.Constants;
|
||||||
|
import awais.instagrabber.utils.LocaleUtils;
|
||||||
import awais.instagrabber.utils.Utils;
|
import awais.instagrabber.utils.Utils;
|
||||||
import awaisomereport.LogCollector;
|
import awaisomereport.LogCollector;
|
||||||
|
|
||||||
@ -84,6 +86,7 @@ public final class iStoryStatusFetcher extends AsyncTask<Void, Void, StoryModel[
|
|||||||
conn.setInstanceFollowRedirects(true);
|
conn.setInstanceFollowRedirects(true);
|
||||||
conn.setUseCaches(false);
|
conn.setUseCaches(false);
|
||||||
conn.setRequestProperty("User-Agent", storiesig ? Constants.A_USER_AGENT : Constants.I_USER_AGENT);
|
conn.setRequestProperty("User-Agent", storiesig ? Constants.A_USER_AGENT : Constants.I_USER_AGENT);
|
||||||
|
conn.setRequestProperty("Accept-Language", LocaleUtils.getCurrentLocale().getLanguage() + ",en-US;q=0.8");
|
||||||
conn.connect();
|
conn.connect();
|
||||||
|
|
||||||
if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
|
if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
|
||||||
@ -121,6 +124,7 @@ public final class iStoryStatusFetcher extends AsyncTask<Void, Void, StoryModel[
|
|||||||
models[i].setTappableShortCode(data.getJSONArray("story_feed_media").getJSONObject(0).optString("media_id"));
|
models[i].setTappableShortCode(data.getJSONArray("story_feed_media").getJSONObject(0).optString("media_id"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// assuming everything is spotify
|
||||||
if (!data.isNull("story_app_attribution"))
|
if (!data.isNull("story_app_attribution"))
|
||||||
models[i].setSpotify(data.getJSONObject("story_app_attribution").optString("content_url").split("\\?")[0]);
|
models[i].setSpotify(data.getJSONObject("story_app_attribution").optString("content_url").split("\\?")[0]);
|
||||||
|
|
||||||
@ -136,6 +140,7 @@ public final class iStoryStatusFetcher extends AsyncTask<Void, Void, StoryModel[
|
|||||||
tappableObject.optInt("viewer_vote", -1)
|
tappableObject.optInt("viewer_vote", -1)
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.has("story_questions")) {
|
if (data.has("story_questions")) {
|
||||||
JSONObject tappableObject = data.getJSONArray("story_questions").getJSONObject(0).optJSONObject("question_sticker");
|
JSONObject tappableObject = data.getJSONArray("story_questions").getJSONObject(0).optJSONObject("question_sticker");
|
||||||
if (tappableObject != null && !tappableObject.getString("question_type").equals("music"))
|
if (tappableObject != null && !tappableObject.getString("question_type").equals("music"))
|
||||||
@ -144,6 +149,7 @@ public final class iStoryStatusFetcher extends AsyncTask<Void, Void, StoryModel[
|
|||||||
tappableObject.getString("question")
|
tappableObject.getString("question")
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.has("story_quizs")) {
|
if (data.has("story_quizs")) {
|
||||||
JSONObject tappableObject = data.getJSONArray("story_quizs").getJSONObject(0).optJSONObject("quiz_sticker");
|
JSONObject tappableObject = data.getJSONArray("story_quizs").getJSONObject(0).optJSONObject("quiz_sticker");
|
||||||
if (tappableObject != null) {
|
if (tappableObject != null) {
|
||||||
@ -164,6 +170,18 @@ public final class iStoryStatusFetcher extends AsyncTask<Void, Void, StoryModel[
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (data.has("story_cta") && data.has("link_text")) {
|
||||||
|
JSONObject tappableObject = data.getJSONArray("story_cta").getJSONObject(0).getJSONArray("links").getJSONObject(0);
|
||||||
|
String swipeUpUrl = tappableObject.getString("webUri");
|
||||||
|
if (swipeUpUrl.startsWith("http")) {
|
||||||
|
models[i].setSwipeUp(new SwipeUpModel(
|
||||||
|
swipeUpUrl,
|
||||||
|
data.getString("link_text")
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
JSONArray hashtags = data.optJSONArray("story_hashtags");
|
JSONArray hashtags = data.optJSONArray("story_hashtags");
|
||||||
JSONArray locations = data.optJSONArray("story_locations");
|
JSONArray locations = data.optJSONArray("story_locations");
|
||||||
JSONArray atmarks = data.optJSONArray("reel_mentions");
|
JSONArray atmarks = data.optJSONArray("reel_mentions");
|
||||||
|
@ -47,7 +47,7 @@ public class DirectMessageInboxFragment extends Fragment implements SwipeRefresh
|
|||||||
private String endCursor;
|
private String endCursor;
|
||||||
private AsyncTask<Void, Void, InboxModel> currentlyRunning;
|
private AsyncTask<Void, Void, InboxModel> currentlyRunning;
|
||||||
private InboxThreadModelListViewModel listViewModel;
|
private InboxThreadModelListViewModel listViewModel;
|
||||||
public static boolean afterLeave = false;
|
public static boolean refreshPlease = false;
|
||||||
|
|
||||||
private final FetchListener<InboxModel> fetchListener = new FetchListener<InboxModel>() {
|
private final FetchListener<InboxModel> fetchListener = new FetchListener<InboxModel>() {
|
||||||
@Override
|
@Override
|
||||||
@ -121,9 +121,9 @@ public class DirectMessageInboxFragment extends Fragment implements SwipeRefresh
|
|||||||
@Override
|
@Override
|
||||||
public void onResume() {
|
public void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
if (afterLeave) {
|
if (refreshPlease) {
|
||||||
onRefresh();
|
onRefresh();
|
||||||
afterLeave = false;
|
refreshPlease = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -199,7 +199,7 @@ public class DirectMessageSettingsFragment extends Fragment implements SwipeRefr
|
|||||||
titleText.clearFocus();
|
titleText.clearFocus();
|
||||||
}
|
}
|
||||||
else if (action.equals("leave")) {
|
else if (action.equals("leave")) {
|
||||||
DirectMessageInboxFragment.afterLeave = true;
|
DirectMessageInboxFragment.refreshPlease = true;
|
||||||
NavHostFragment.findNavController(DirectMessageSettingsFragment.this).popBackStack(R.id.directMessagesInboxFragment, false);
|
NavHostFragment.findNavController(DirectMessageSettingsFragment.this).popBackStack(R.id.directMessagesInboxFragment, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -66,6 +66,7 @@ import awais.instagrabber.models.direct_messages.DirectItemModel;
|
|||||||
import awais.instagrabber.models.direct_messages.InboxThreadModel;
|
import awais.instagrabber.models.direct_messages.InboxThreadModel;
|
||||||
import awais.instagrabber.models.enums.DirectItemType;
|
import awais.instagrabber.models.enums.DirectItemType;
|
||||||
import awais.instagrabber.models.enums.DownloadMethod;
|
import awais.instagrabber.models.enums.DownloadMethod;
|
||||||
|
import awais.instagrabber.models.enums.MediaItemType;
|
||||||
import awais.instagrabber.models.enums.UserInboxDirection;
|
import awais.instagrabber.models.enums.UserInboxDirection;
|
||||||
import awais.instagrabber.utils.Constants;
|
import awais.instagrabber.utils.Constants;
|
||||||
import awais.instagrabber.utils.Utils;
|
import awais.instagrabber.utils.Utils;
|
||||||
@ -208,6 +209,7 @@ public class DirectMessageThreadFragment extends Fragment {
|
|||||||
final DirectItemType itemType = directItemModel.getItemType();
|
final DirectItemType itemType = directItemModel.getItemType();
|
||||||
switch (itemType) {
|
switch (itemType) {
|
||||||
case MEDIA_SHARE:
|
case MEDIA_SHARE:
|
||||||
|
case CLIP:
|
||||||
startActivity(new Intent(requireContext(), PostViewer.class)
|
startActivity(new Intent(requireContext(), PostViewer.class)
|
||||||
.putExtra(Constants.EXTRAS_POST, new PostModel(directItemModel.getMediaModel().getCode(), false)));
|
.putExtra(Constants.EXTRAS_POST, new PostModel(directItemModel.getMediaModel().getCode(), false)));
|
||||||
break;
|
break;
|
||||||
@ -224,8 +226,16 @@ public class DirectMessageThreadFragment extends Fragment {
|
|||||||
case RAVEN_MEDIA:
|
case RAVEN_MEDIA:
|
||||||
case MEDIA:
|
case MEDIA:
|
||||||
final ProfileModel user = getUser(directItemModel.getUserId());
|
final ProfileModel user = getUser(directItemModel.getUserId());
|
||||||
Utils.dmDownload(requireContext(), user.getUsername(), DownloadMethod.DOWNLOAD_DIRECT, Collections.singletonList(itemType == DirectItemType.MEDIA ? directItemModel.getMediaModel() : directItemModel.getRavenMediaModel().getMedia()));
|
final DirectItemModel.DirectItemMediaModel selectedItem =
|
||||||
Toast.makeText(requireContext(), R.string.downloader_downloading_media, Toast.LENGTH_SHORT).show();
|
itemType == DirectItemType.MEDIA ? directItemModel.getMediaModel() : directItemModel.getRavenMediaModel().getMedia();
|
||||||
|
final String url = selectedItem.getMediaType() == MediaItemType.MEDIA_TYPE_VIDEO ? selectedItem.getVideoUrl() : selectedItem.getThumbUrl();
|
||||||
|
if (url == null) {
|
||||||
|
Toast.makeText(requireContext(), R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Utils.dmDownload(requireContext(), user.getUsername(), DownloadMethod.DOWNLOAD_DIRECT, selectedItem);
|
||||||
|
Toast.makeText(requireContext(), R.string.downloader_downloading_media, Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case STORY_SHARE:
|
case STORY_SHARE:
|
||||||
if (directItemModel.getReelShare() != null) {
|
if (directItemModel.getReelShare() != null) {
|
||||||
@ -275,6 +285,7 @@ public class DirectMessageThreadFragment extends Fragment {
|
|||||||
|
|
||||||
switch (itemType) {
|
switch (itemType) {
|
||||||
case MEDIA_SHARE:
|
case MEDIA_SHARE:
|
||||||
|
case CLIP:
|
||||||
firstOption = R.string.view_post;
|
firstOption = R.string.view_post;
|
||||||
break;
|
break;
|
||||||
case LINK:
|
case LINK:
|
||||||
@ -376,6 +387,7 @@ public class DirectMessageThreadFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
directItemModel.setLiked();
|
directItemModel.setLiked();
|
||||||
}
|
}
|
||||||
|
DirectMessageInboxFragment.refreshPlease = true;
|
||||||
hasSentSomething = true;
|
hasSentSomething = true;
|
||||||
new DirectMessageInboxThreadFetcher(threadId, UserInboxDirection.OLDER, null, fetchListener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
new DirectMessageInboxThreadFetcher(threadId, UserInboxDirection.OLDER, null, fetchListener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
});
|
});
|
||||||
|
@ -6,6 +6,7 @@ import awais.instagrabber.models.enums.MediaItemType;
|
|||||||
import awais.instagrabber.models.stickers.PollModel;
|
import awais.instagrabber.models.stickers.PollModel;
|
||||||
import awais.instagrabber.models.stickers.QuestionModel;
|
import awais.instagrabber.models.stickers.QuestionModel;
|
||||||
import awais.instagrabber.models.stickers.QuizModel;
|
import awais.instagrabber.models.stickers.QuizModel;
|
||||||
|
import awais.instagrabber.models.stickers.SwipeUpModel;
|
||||||
|
|
||||||
public final class StoryModel implements Serializable {
|
public final class StoryModel implements Serializable {
|
||||||
private final String storyMediaId, storyUrl, username, userId;
|
private final String storyMediaId, storyUrl, username, userId;
|
||||||
@ -15,6 +16,7 @@ public final class StoryModel implements Serializable {
|
|||||||
private PollModel poll;
|
private PollModel poll;
|
||||||
private QuestionModel question;
|
private QuestionModel question;
|
||||||
private QuizModel quiz;
|
private QuizModel quiz;
|
||||||
|
private SwipeUpModel swipeUp;
|
||||||
private String[] mentions;
|
private String[] mentions;
|
||||||
private int position;
|
private int position;
|
||||||
private boolean isCurrentSlide = false, canReply = false;
|
private boolean isCurrentSlide = false, canReply = false;
|
||||||
@ -66,6 +68,8 @@ public final class StoryModel implements Serializable {
|
|||||||
return quiz;
|
return quiz;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SwipeUpModel getSwipeUp() { return swipeUp;}
|
||||||
|
|
||||||
public String[] getMentions() {
|
public String[] getMentions() {
|
||||||
return mentions;
|
return mentions;
|
||||||
}
|
}
|
||||||
@ -106,6 +110,10 @@ public final class StoryModel implements Serializable {
|
|||||||
this.mentions = mentions;
|
this.mentions = mentions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setSwipeUp(final SwipeUpModel swipeUp) {
|
||||||
|
this.swipeUp = swipeUp;
|
||||||
|
}
|
||||||
|
|
||||||
public void setPosition(final int position) {
|
public void setPosition(final int position) {
|
||||||
this.position = position;
|
this.position = position;
|
||||||
}
|
}
|
||||||
|
@ -5,8 +5,7 @@ import org.json.JSONObject;
|
|||||||
import awais.instagrabber.models.enums.MediaItemType;
|
import awais.instagrabber.models.enums.MediaItemType;
|
||||||
|
|
||||||
public final class ViewerPostModel extends BasePostModel {
|
public final class ViewerPostModel extends BasePostModel {
|
||||||
protected final String username;
|
protected final String username, locationName, location;
|
||||||
protected final JSONObject location;
|
|
||||||
protected final long videoViews;
|
protected final long videoViews;
|
||||||
protected String sliderDisplayUrl;
|
protected String sliderDisplayUrl;
|
||||||
protected long commentsCount, likes;
|
protected long commentsCount, likes;
|
||||||
@ -14,7 +13,7 @@ public final class ViewerPostModel extends BasePostModel {
|
|||||||
|
|
||||||
public ViewerPostModel(final MediaItemType itemType, final String postId, final String displayUrl, final String shortCode,
|
public ViewerPostModel(final MediaItemType itemType, final String postId, final String displayUrl, final String shortCode,
|
||||||
final String postCaption, final String username, final long videoViews, final long timestamp,
|
final String postCaption, final String username, final long videoViews, final long timestamp,
|
||||||
boolean liked, boolean bookmarked, long likes, final JSONObject location) {
|
boolean liked, boolean bookmarked, long likes, final String locationName, final String location) {
|
||||||
this.itemType = itemType;
|
this.itemType = itemType;
|
||||||
this.postId = postId;
|
this.postId = postId;
|
||||||
this.displayUrl = displayUrl;
|
this.displayUrl = displayUrl;
|
||||||
@ -26,6 +25,7 @@ public final class ViewerPostModel extends BasePostModel {
|
|||||||
this.liked = liked;
|
this.liked = liked;
|
||||||
this.likes = likes;
|
this.likes = likes;
|
||||||
this.bookmarked = bookmarked;
|
this.bookmarked = bookmarked;
|
||||||
|
this.locationName = locationName;
|
||||||
this.location = location;
|
this.location = location;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,7 +41,11 @@ public final class ViewerPostModel extends BasePostModel {
|
|||||||
return username;
|
return username;
|
||||||
}
|
}
|
||||||
|
|
||||||
public JSONObject getLocation() {
|
public String getLocationName() {
|
||||||
|
return locationName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLocation() {
|
||||||
return location;
|
return location;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,7 +18,8 @@ public enum DirectItemType implements Serializable {
|
|||||||
REEL_SHARE(11),
|
REEL_SHARE(11),
|
||||||
ACTION_LOG(12),
|
ACTION_LOG(12),
|
||||||
PLACEHOLDER(13),
|
PLACEHOLDER(13),
|
||||||
STORY_SHARE(14);
|
STORY_SHARE(14),
|
||||||
|
CLIP(15); // clip is just media_share but reel
|
||||||
|
|
||||||
private final int id;
|
private final int id;
|
||||||
private static Map<Integer, DirectItemType> map = new HashMap<>();
|
private static Map<Integer, DirectItemType> map = new HashMap<>();
|
||||||
|
20
app/src/main/java/awais/instagrabber/models/stickers/SwipeUpModel.java
Executable file
20
app/src/main/java/awais/instagrabber/models/stickers/SwipeUpModel.java
Executable file
@ -0,0 +1,20 @@
|
|||||||
|
package awais.instagrabber.models.stickers;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
public final class SwipeUpModel implements Serializable {
|
||||||
|
private final String url, text;
|
||||||
|
|
||||||
|
public SwipeUpModel(final String url, final String text) {
|
||||||
|
this.url = url;
|
||||||
|
this.text = text;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUrl() {
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getText() {
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
}
|
@ -144,10 +144,10 @@ public final class Utils {
|
|||||||
final URI uri1 = new URI("https://instagram.com");
|
final URI uri1 = new URI("https://instagram.com");
|
||||||
final URI uri2 = new URI("https://instagram.com/");
|
final URI uri2 = new URI("https://instagram.com/");
|
||||||
final URI uri3 = new URI("https://i.instagram.com/");
|
final URI uri3 = new URI("https://i.instagram.com/");
|
||||||
for (final String cookie : cookieRaw.split(";")) {
|
for (final String cookie : cookieRaw.split("; ")) {
|
||||||
final String[] strings = cookie.split("=", 2);
|
final String[] strings = cookie.split("=", 2);
|
||||||
final HttpCookie httpCookie = new HttpCookie(strings[0].trim(), strings[1].trim());
|
final HttpCookie httpCookie = new HttpCookie(strings[0].trim(), strings[1].trim());
|
||||||
httpCookie.setDomain("instagram.com");
|
httpCookie.setDomain(".instagram.com");
|
||||||
httpCookie.setPath("/");
|
httpCookie.setPath("/");
|
||||||
httpCookie.setVersion(0);
|
httpCookie.setVersion(0);
|
||||||
cookieStore.add(uri1, httpCookie);
|
cookieStore.add(uri1, httpCookie);
|
||||||
@ -427,7 +427,7 @@ public final class Utils {
|
|||||||
if (userObj != null) {
|
if (userObj != null) {
|
||||||
user = new ProfileModel(
|
user = new ProfileModel(
|
||||||
userObj.getBoolean("is_private"),
|
userObj.getBoolean("is_private"),
|
||||||
false, // temporary
|
false,
|
||||||
userObj.optBoolean("is_verified"),
|
userObj.optBoolean("is_verified"),
|
||||||
String.valueOf(userObj.get("pk")),
|
String.valueOf(userObj.get("pk")),
|
||||||
userObj.getString("username"),
|
userObj.getString("username"),
|
||||||
@ -468,6 +468,7 @@ public final class Utils {
|
|||||||
if ("animated_media".equals(itemType)) return DirectItemType.ANIMATED_MEDIA;
|
if ("animated_media".equals(itemType)) return DirectItemType.ANIMATED_MEDIA;
|
||||||
if ("voice_media".equals(itemType)) return DirectItemType.VOICE_MEDIA;
|
if ("voice_media".equals(itemType)) return DirectItemType.VOICE_MEDIA;
|
||||||
if ("story_share".equals(itemType)) return DirectItemType.STORY_SHARE;
|
if ("story_share".equals(itemType)) return DirectItemType.STORY_SHARE;
|
||||||
|
if ("clip".equals(itemType)) return DirectItemType.CLIP;
|
||||||
return DirectItemType.TEXT;
|
return DirectItemType.TEXT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -708,6 +709,11 @@ public final class Utils {
|
|||||||
directMedia = getDirectMediaModel(itemObject.getJSONObject("media_share"));
|
directMedia = getDirectMediaModel(itemObject.getJSONObject("media_share"));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case CLIP:
|
||||||
|
Log.d("austin_debug", "clip: "+itemObject.getJSONObject("clip").getJSONObject("clip"));
|
||||||
|
directMedia = getDirectMediaModel(itemObject.getJSONObject("clip").getJSONObject("clip"));
|
||||||
|
break;
|
||||||
|
|
||||||
case MEDIA:
|
case MEDIA:
|
||||||
directMedia = getDirectMediaModel(itemObject.optJSONObject("media"));
|
directMedia = getDirectMediaModel(itemObject.optJSONObject("media"));
|
||||||
break;
|
break;
|
||||||
@ -999,10 +1005,10 @@ public final class Utils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void dmDownload(@NonNull final Context context, @Nullable final String username, final DownloadMethod method,
|
public static void dmDownload(@NonNull final Context context, @Nullable final String username, final DownloadMethod method,
|
||||||
final List<? extends DirectItemMediaModel> itemsToDownload) {
|
final DirectItemMediaModel itemsToDownload) {
|
||||||
if (settingsHelper == null) settingsHelper = new SettingsHelper(context);
|
if (settingsHelper == null) settingsHelper = new SettingsHelper(context);
|
||||||
|
|
||||||
if (itemsToDownload == null || itemsToDownload.size() < 1) return;
|
if (itemsToDownload == null) return;
|
||||||
|
|
||||||
if (ContextCompat.checkSelfPermission(context, Utils.PERMS[0]) == PackageManager.PERMISSION_GRANTED)
|
if (ContextCompat.checkSelfPermission(context, Utils.PERMS[0]) == PackageManager.PERMISSION_GRANTED)
|
||||||
dmDownloadImpl(context, username, method, itemsToDownload);
|
dmDownloadImpl(context, username, method, itemsToDownload);
|
||||||
@ -1011,7 +1017,7 @@ public final class Utils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void dmDownloadImpl(@NonNull final Context context, @Nullable final String username,
|
private static void dmDownloadImpl(@NonNull final Context context, @Nullable final String username,
|
||||||
final DownloadMethod method, final List<? extends DirectItemMediaModel> itemsToDownload) {
|
final DownloadMethod method, final DirectItemMediaModel selectedItem) {
|
||||||
File dir = new File(Environment.getExternalStorageDirectory(), "Download");
|
File dir = new File(Environment.getExternalStorageDirectory(), "Download");
|
||||||
|
|
||||||
if (settingsHelper.getBoolean(FOLDER_SAVE_TO)) {
|
if (settingsHelper.getBoolean(FOLDER_SAVE_TO)) {
|
||||||
@ -1023,22 +1029,11 @@ public final class Utils {
|
|||||||
dir = new File(dir, username);
|
dir = new File(dir, username);
|
||||||
|
|
||||||
if (dir.exists() || dir.mkdirs()) {
|
if (dir.exists() || dir.mkdirs()) {
|
||||||
final MainActivity mainActivity = method != DownloadMethod.DOWNLOAD_FEED && context instanceof MainActivity ? (MainActivity) context : null;
|
|
||||||
|
|
||||||
final int itemsToDownloadSize = itemsToDownload.size();
|
|
||||||
|
|
||||||
final File finalDir = dir;
|
final File finalDir = dir;
|
||||||
for (int i = itemsToDownloadSize - 1; i >= 0; i--) {
|
new DownloadAsync(context,
|
||||||
final DirectItemMediaModel selectedItem = itemsToDownload.get(i);
|
selectedItem.getMediaType() == MediaItemType.MEDIA_TYPE_VIDEO ? selectedItem.getVideoUrl() : selectedItem.getThumbUrl(),
|
||||||
|
getDownloadSaveFileDm(finalDir, selectedItem, ""),
|
||||||
if (mainActivity == null) {
|
null).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
new DownloadAsync(context,
|
|
||||||
selectedItem.getMediaType() == MediaItemType.MEDIA_TYPE_VIDEO ? selectedItem.getVideoUrl() : selectedItem.getThumbUrl(),
|
|
||||||
getDownloadSaveFileDm(finalDir, selectedItem, ""),
|
|
||||||
null).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else
|
} else
|
||||||
Toast.makeText(context, R.string.error_creating_folders, Toast.LENGTH_SHORT).show();
|
Toast.makeText(context, R.string.error_creating_folders, Toast.LENGTH_SHORT).show();
|
||||||
}
|
}
|
||||||
@ -1256,7 +1251,7 @@ public final class Utils {
|
|||||||
|
|
||||||
final int endIndex = (spaceIndex != -1 ? spaceIndex : length);
|
final int endIndex = (spaceIndex != -1 ? spaceIndex : length);
|
||||||
|
|
||||||
final String extractUrl = url.substring(startIndex, Math.min(length, endIndex) - 1);
|
final String extractUrl = url.substring(startIndex, Math.min(length, endIndex));
|
||||||
|
|
||||||
final SpannableString spannableString = new SpannableString(url);
|
final SpannableString spannableString = new SpannableString(url);
|
||||||
spannableString.setSpan(new URLSpan(extractUrl), startIndex, endIndex, 0);
|
spannableString.setSpan(new URLSpan(extractUrl), startIndex, endIndex, 0);
|
||||||
|
@ -85,6 +85,15 @@
|
|||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
app:backgroundTint="@color/btn_blue_background" />
|
app:backgroundTint="@color/btn_blue_background" />
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatButton
|
||||||
|
android:id="@+id/swipeUp"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:text="SAMPLE TEXT"
|
||||||
|
android:textColor="@color/btn_blue_text_color"
|
||||||
|
android:visibility="gone"
|
||||||
|
app:backgroundTint="@color/btn_blue_background" />
|
||||||
<androidx.appcompat.widget.AppCompatButton
|
<androidx.appcompat.widget.AppCompatButton
|
||||||
android:id="@+id/mention"
|
android:id="@+id/mention"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
@ -46,6 +46,7 @@
|
|||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:textAppearance="@style/TextAppearance.AppCompat.Subhead"
|
android:textAppearance="@style/TextAppearance.AppCompat.Subhead"
|
||||||
android:textColor="@color/feed_text_primary_color"
|
android:textColor="@color/feed_text_primary_color"
|
||||||
|
android:textSize="15sp" />
|
||||||
tools:text="location" />
|
tools:text="location" />
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user