Skip to content
This repository was archived by the owner on Feb 20, 2026. It is now read-only.

Commit 28716f5

Browse files
committed
new: design
1 parent 96c74b1 commit 28716f5

83 files changed

Lines changed: 2735 additions & 1187 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

V2rayNG/app/build.gradle

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ android {
3434
minSdkVersion 21
3535
targetSdkVersion Integer.parseInt("$targetSdkVer")
3636
multiDexEnabled true
37-
versionCode 5100554 //hiddify when comes to version 5 change it
38-
versionName "5.5.4" //hiddify
37+
versionCode 5100600 //hiddify when comes to version 5 change it
38+
versionName "6.0.0" //hiddify
3939
}
4040

4141
signingConfigs {
@@ -70,7 +70,7 @@ android {
7070
ndk.abiFilters 'x86', 'x86_64', 'armeabi-v7a', 'arm64-v8a'
7171
// applicationIdSuffix '.debug'
7272
// android.defaultConfig.applicationId "ang.hiddify.com.debug"
73-
versionNameSuffix '-DEBUG'
73+
versionNameSuffix 'd'
7474
}
7575
}
7676

@@ -133,6 +133,7 @@ android {
133133

134134
dependencies {
135135
implementation fileTree(dir: 'libs', include: ['*.aar', '*.jar'], exclude: [])
136+
implementation 'androidx.coordinatorlayout:coordinatorlayout:1.2.0'
136137
testImplementation 'junit:junit:4.13.2'
137138

138139
// Androidx
@@ -239,6 +240,12 @@ dependencies {
239240

240241
// implementation("org.symphonyoss.symphony:jcurl:0.9.18")
241242

243+
implementation 'com.github.tapadoo:alerter:7.2.4'
244+
// implementation 'com.github.Yalantis:Context-Menu.Android:1.1.4'
245+
// implementation 'com.github.dmytrodanylyk:circular-progress-button:1.3'
246+
// compile 'com.github.dmytrodanylyk:android-morphing-button:1.0'
247+
implementation 'com.github.anastr:speedviewlib:1.6.0'
248+
242249

243250

244251

V2rayNG/app/src/main/AndroidManifest.xml

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
android:icon="@mipmap/ic_launcher"
3232
android:label="@string/app_name"
3333
android:supportsRtl="true"
34-
android:theme="@style/AppThemeDayNight"
34+
android:theme="@style/AppTheme"
3535
android:usesCleartextTraffic="true"
3636
tools:targetApi="m">
3737
<provider
@@ -62,26 +62,21 @@
6262
android:name="com.hiddify.ang.speedtest.SpeedTestActivity"
6363
android:exported="true"
6464
android:launchMode="singleTask"
65-
android:theme="@style/AppThemeDayNight.NoActionBar">
65+
android:theme="@style/AppTheme">
6666

6767

6868
</activity>
69+
70+
6971
<activity
70-
android:name=".ui.MainActivity"
72+
android:name=".ui.HomeActivity"
7173
android:exported="true"
7274
android:launchMode="singleTask"
73-
android:theme="@style/AppThemeDayNight.NoActionBar">
74-
75+
android:theme="@style/AppTheme">
7576

7677
<meta-data
7778
android:name="android.app.shortcuts"
7879
android:resource="@xml/shortcuts" />
79-
</activity>
80-
<activity
81-
android:name=".ui.HiddifyMainActivity"
82-
android:exported="true"
83-
android:launchMode="singleTask"
84-
android:theme="@style/AppThemeDayNight.NoActionBar">
8580
<intent-filter>
8681
<action android:name="android.service.quicksettings.action.QS_TILE_PREFERENCES" />
8782
</intent-filter>
@@ -127,7 +122,7 @@
127122
android:excludeFromRecents="true"
128123
android:exported="false"
129124
android:process=":RunSoLibV2RayDaemon"
130-
android:theme="@style/AppTheme.NoActionBar.Translucent" />
125+
android:theme="@style/AppTheme" />
131126
<activity
132127
android:name=".ui.UrlSchemeActivity"
133128
android:exported="true">
Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,27 @@
11
package com.v2ray.ang.dto
22

33
data class SubscriptionItem(
4-
var remarks: String = "",
5-
var url: String = "",
6-
var enabled: Boolean = true,
7-
var addedTime: Long = System.currentTimeMillis(),
8-
var lastUpdateTime: Long = 0,
9-
var used: Long=-1,
10-
var total: Long=-1,
11-
var expire: Long=-1,//in ms
12-
var home_link: String="",
13-
var support_link: String="",
14-
var update_interval: Int=1,
15-
var dns: String?=null
16-
) {
17-
4+
var remarks: String = "",
5+
var url: String = "",
6+
var enabled: Boolean = true,
7+
var addedTime: Long = System.currentTimeMillis(),
8+
var lastUpdateTime: Long = 0,
9+
var used: Long = -1,
10+
var total: Long = -1,
11+
var expire: Long = -1,//in ms
12+
var home_link: String = "",
13+
var support_link: String = "",
14+
var update_interval: Int = 1,
15+
var dns: String? = null
16+
) {
1817

1918

2019
fun needUpdate(): Boolean {
21-
if (update_interval<0)return false
22-
var hours = (System.currentTimeMillis() - lastUpdateTime) / (1000 * 60 * 60)
23-
return (hours>=update_interval)
20+
if (url?.startsWith("http") != true) return false
21+
if (update_interval < 0) return false
22+
var hours = (System.currentTimeMillis() - lastUpdateTime) / (1000 * 60 * 60)
23+
return (hours >= update_interval)
2424

2525

26-
}
26+
}
2727
}

V2rayNG/app/src/main/kotlin/com/v2ray/ang/extension/_HiddifyExt.kt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import android.view.View
1616
import android.widget.TextView
1717
import android.widget.Toast
1818
import androidx.core.content.ContextCompat
19+
import com.tapadoo.alerter.Alerter
1920
import com.v2ray.ang.AngApplication
2021
import com.v2ray.ang.R
2122
import com.v2ray.ang.util.Utils
@@ -196,7 +197,10 @@ fun Context?.toast(s: String?, length : Int = Toast.LENGTH_SHORT) {
196197
if (s == null || s.isBlank()) {
197198
return
198199
}
199-
200+
Alerter.create(this as Activity)
201+
// .setTitle("Alert Title")
202+
.setText(s)
203+
.show()
200204
val inflater = LayoutInflater.from(this)
201205
val layout = inflater.inflate(R.layout.custom_toast, null)
202206
val text = layout.findViewById<TextView>(R.id.text)
Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
package com.v2ray.ang.ui
2+
3+
import android.content.Intent
4+
import android.os.Bundle
5+
import android.view.LayoutInflater
6+
import android.view.View
7+
import android.view.ViewGroup
8+
//import androidx.fragment.app.dialogFragment
9+
import androidx.fragment.app.Fragment
10+
11+
import com.hiddify.ang.speedtest.SpeedTestActivity
12+
import com.v2ray.ang.R
13+
import com.v2ray.ang.databinding.BottomsheetSettingBinding
14+
import com.v2ray.ang.extension.click
15+
import com.v2ray.ang.ui.PerAppProxyActivity
16+
import com.v2ray.ang.util.CallbackUtil
17+
import com.v2ray.ang.util.HiddifyUtils
18+
import com.v2ray.ang.util.Utils
19+
20+
class HiddifyAdvancedFragment() : Fragment() {
21+
public lateinit var binding: BottomsheetSettingBinding
22+
23+
interface Callback {
24+
fun onModeChange(mode: Int)
25+
fun onPerAppProxyModeChange(mode: HiddifyUtils.PerAppProxyMode)
26+
fun onFragmentModeChange(mode: HiddifyUtils.FragmentMode)
27+
}
28+
29+
30+
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
31+
inflater.inflate(R.layout.bottomsheet_setting, container, false)
32+
binding = BottomsheetSettingBinding.inflate(inflater, container, false)
33+
34+
binding.connectToggleButton.check(when (HiddifyUtils.getMode()) {
35+
1 -> binding.smart.id
36+
2 -> binding.loadBalance.id
37+
else -> binding.manual.id
38+
})
39+
binding.connectToggleButton.addOnButtonCheckedListener { group, checkedId, isChecked ->
40+
if (isChecked) {
41+
val mode = when (checkedId) {
42+
binding.smart.id ->1
43+
binding.loadBalance.id ->2
44+
else ->3
45+
}
46+
callback()?.onModeChange(mode)
47+
}else if (group.checkedButtonIds.isEmpty()) {
48+
// No buttons are selected, select the first one by default
49+
50+
group.check(when (HiddifyUtils.getMode()) {
51+
1 -> binding.smart.id
52+
2 -> binding.loadBalance.id
53+
else -> binding.manual.id
54+
})
55+
}
56+
}
57+
58+
59+
60+
61+
62+
63+
64+
binding.speedtest.click{
65+
//SpeedTester.showSpeedTest//dialog(this)
66+
startActivity(Intent(context, SpeedTestActivity::class.java))
67+
}
68+
69+
70+
binding.proxyToggleButton.check(when (HiddifyUtils.getPerAppProxyMode()) {
71+
HiddifyUtils.PerAppProxyMode.NotOpened -> binding.notOpened.id
72+
HiddifyUtils.PerAppProxyMode.Blocked -> binding.filteredSites.id
73+
else -> binding.sitesAll.id
74+
})
75+
binding.proxyToggleButton.setOnLongClickListener{
76+
startActivity(Intent(activity, PerAppProxyActivity::class.java))
77+
//dialog?.dismiss()
78+
true;
79+
}
80+
binding.sitesAll.setOnLongClickListener{
81+
HiddifyUtils.setPerAppProxyMode(HiddifyUtils.PerAppProxyMode.NotOpened)
82+
startActivity(Intent(activity, PerAppProxyActivity::class.java))
83+
//dialog?.dismiss()
84+
true;
85+
}
86+
binding.notOpened.setOnLongClickListener{
87+
HiddifyUtils.setPerAppProxyMode(HiddifyUtils.PerAppProxyMode.NotOpened)
88+
startActivity(Intent(activity, PerAppProxyActivity::class.java))
89+
//dialog?.dismiss()
90+
true;
91+
}
92+
binding.filteredSites.setOnLongClickListener{
93+
HiddifyUtils.setPerAppProxyMode(HiddifyUtils.PerAppProxyMode.Blocked)
94+
startActivity(Intent(activity, PerAppProxyActivity::class.java))
95+
//dialog?.dismiss()
96+
true;
97+
}
98+
binding.proxyToggleButton.addOnButtonCheckedListener { group, checkedId, isChecked ->
99+
if (isChecked) {
100+
val mode = when (checkedId) {
101+
binding.notOpened.id->HiddifyUtils.PerAppProxyMode.NotOpened
102+
binding.filteredSites.id->HiddifyUtils.PerAppProxyMode.Blocked
103+
else -> HiddifyUtils.PerAppProxyMode.Global
104+
}
105+
callback()?.onPerAppProxyModeChange(mode)
106+
}else if (group.checkedButtonIds.isEmpty()) {
107+
// No buttons are selected, select the first one by default
108+
109+
group.check(when (HiddifyUtils.getPerAppProxyMode()) {
110+
HiddifyUtils.PerAppProxyMode.NotOpened -> binding.notOpened.id
111+
HiddifyUtils.PerAppProxyMode.Blocked -> binding.filteredSites.id
112+
else -> binding.sitesAll.id
113+
})
114+
}
115+
}
116+
binding.fragment.check(when (HiddifyUtils.getFragmentMode()) {
117+
HiddifyUtils.FragmentMode.SNI -> binding.fragmentSni.id
118+
HiddifyUtils.FragmentMode.Random -> binding.fragmentRandom.id
119+
else -> binding.fragmentDefault.id
120+
})
121+
binding.fragment.addOnButtonCheckedListener { group, checkedId, isChecked ->
122+
if (isChecked) {
123+
val mode = when (checkedId) {
124+
binding.fragmentSni.id->HiddifyUtils.FragmentMode.SNI
125+
binding.fragmentRandom.id->HiddifyUtils.FragmentMode.Random
126+
else -> HiddifyUtils.FragmentMode.Default
127+
}
128+
callback()?.onFragmentModeChange(mode)
129+
}else if (group.checkedButtonIds.isEmpty()) {
130+
// No buttons are selected, select the first one by default
131+
// callback()?.onFragmentModeChange(mode)
132+
}
133+
}
134+
135+
binding.proxymodeHelp.click {
136+
Utils.openUri(requireContext(),requireContext().getString(R.string.proxymode_help_url))
137+
}
138+
binding.fragmentHelp.click {
139+
Utils.openUri(requireContext(),requireContext().getString(R.string.fragment_help_url))
140+
}
141+
binding.connectionModeHelp.click {
142+
Utils.openUri(requireContext(),requireContext().getString(R.string.connection_mode_help_url))
143+
}
144+
return binding.root
145+
}
146+
147+
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
148+
super.onViewCreated(view, savedInstanceState)
149+
}
150+
151+
private fun callback(): Callback? {
152+
return CallbackUtil.getCallback(this, Callback::class.java)
153+
}
154+
155+
companion object {
156+
fun newInstance(mode: Int): HiddifyAdvancedFragment {
157+
return HiddifyAdvancedFragment()
158+
}
159+
}
160+
161+
override fun onResume() {
162+
super.onResume()
163+
(requireActivity() as BaseActivity).supportActionBar?.title=getText(R.string.advanced)
164+
}
165+
}

0 commit comments

Comments
 (0)