2121import us .shandian .giga .util .Utility ;
2222
2323import static org .schabi .newpipe .BuildConfig .DEBUG ;
24+ import static us .shandian .giga .get .DownloadMission .ERROR_NOTHING ;
25+ import static us .shandian .giga .get .DownloadMission .ERROR_PROGRESS_LOST ;
2426
2527public class DownloadManager {
2628 private static final String TAG = DownloadManager .class .getSimpleName ();
@@ -146,12 +148,31 @@ private void loadPendingMissions(Context ctx) {
146148 if (sub .getName ().equals (".tmp" )) continue ;
147149
148150 DownloadMission mis = Utility .readFromFile (sub );
149- if (mis == null || mis . isFinished () || mis . hasInvalidStorage () ) {
151+ if (mis == null ) {
150152 //noinspection ResultOfMethodCallIgnored
151153 sub .delete ();
152154 continue ;
153155 }
154156
157+ // DON'T delete missions that are truly finished - let them be moved to finished list
158+ if (mis .isFinished ()) {
159+ // Move to finished missions instead of deleting
160+ setFinished (mis );
161+ //noinspection ResultOfMethodCallIgnored
162+ sub .delete ();
163+ continue ;
164+ }
165+
166+ // DON'T delete missions with storage issues - try to recover them
167+ if (mis .hasInvalidStorage () && mis .errCode != ERROR_PROGRESS_LOST ) {
168+ // Only delete if it's truly unrecoverable (not just progress lost)
169+ if (mis .storage == null && mis .errCode != ERROR_PROGRESS_LOST ) {
170+ //noinspection ResultOfMethodCallIgnored
171+ sub .delete ();
172+ continue ;
173+ }
174+ }
175+
155176 mis .threads = new Thread [0 ];
156177
157178 boolean exists ;
@@ -160,28 +181,25 @@ private void loadPendingMissions(Context ctx) {
160181 exists = !mis .storage .isInvalid () && mis .storage .existsAsFile ();
161182 } catch (Exception ex ) {
162183 Log .e (TAG , "Failed to load the file source of " + mis .storage .toString (), ex );
163- mis . storage . invalidate ();
184+ // Don't invalidate storage immediately - try to recover first
164185 exists = false ;
165186 }
166187
167188 if (mis .isPsRunning ()) {
168189 if (mis .psAlgorithm .worksOnSameFile ) {
169190 // Incomplete post-processing results in a corrupted download file
170- // because the selected algorithm works on the same file to save space.
171- // the file will be deleted if the storage API
172- // is Java IO (avoid showing the "Save as..." dialog)
173191 if (exists && mis .storage .isDirect () && !mis .storage .delete ())
174192 Log .w (TAG , "Unable to delete incomplete download file: " + sub .getPath ());
175193 }
176-
177194 mis .psState = 0 ;
178195 mis .errCode = DownloadMission .ERROR_POSTPROCESSING_STOPPED ;
179196 } else if (!exists ) {
180197 tryRecover (mis );
181-
182- // the progress is lost, reset mission state
183- if (mis .isInitialized ())
184- mis .resetState (true , true , DownloadMission .ERROR_PROGRESS_LOST );
198+ // Keep the mission even if recovery fails - don't reset to ERROR_PROGRESS_LOST
199+ // This allows user to see the failed download and potentially retry
200+ if (mis .isInitialized () && mis .errCode == ERROR_NOTHING ) {
201+ mis .resetState (true , true , ERROR_PROGRESS_LOST );
202+ }
185203 }
186204
187205 if (mis .psAlgorithm != null ) {
@@ -192,6 +210,7 @@ private void loadPendingMissions(Context ctx) {
192210 mis .metadata = sub ;
193211 mis .maxRetry = mPrefMaxRetry ;
194212 mis .mHandler = mHandler ;
213+ mis .context = ctx ;
195214
196215 mMissionsPending .add (mis );
197216 }
@@ -200,6 +219,7 @@ private void loadPendingMissions(Context ctx) {
200219 Collections .sort (mMissionsPending , Comparator .comparingLong (Mission ::getTimestamp ));
201220 }
202221
222+
203223 /**
204224 * Start a new download mission
205225 *
@@ -446,7 +466,7 @@ boolean runMissions() {
446466 continue ;
447467
448468 resumeMission (mission );
449- if (mission .errCode != DownloadMission . ERROR_NOTHING ) continue ;
469+ if (mission .errCode != ERROR_NOTHING ) continue ;
450470
451471 if (mPrefQueueLimit ) return true ;
452472 flag = true ;
@@ -510,6 +530,15 @@ void updateMaximumAttempts() {
510530 }
511531 }
512532
533+ public boolean canRecoverMission (DownloadMission mission ) {
534+ if (mission == null ) return false ;
535+
536+ // Can recover missions with progress lost or storage issues
537+ return mission .errCode == ERROR_PROGRESS_LOST ||
538+ mission .storage == null ||
539+ !mission .storage .existsAsFile ();
540+ }
541+
513542 public MissionState checkForExistingMission (StoredFileHelper storage ) {
514543 synchronized (this ) {
515544 DownloadMission pending = getPendingMission (storage );
@@ -582,8 +611,16 @@ private ArrayList<Object> getSpecialItems() {
582611 ArrayList <Mission > finished = new ArrayList <>(mMissionsFinished );
583612 List <Mission > remove = new ArrayList <>(hidden );
584613
585- // hide missions (if required)
586- remove .removeIf (mission -> pending .remove (mission ) || finished .remove (mission ));
614+ // Don't hide recoverable missions
615+ remove .removeIf (mission -> {
616+ if (mission instanceof DownloadMission ) {
617+ DownloadMission dm = (DownloadMission ) mission ;
618+ if (canRecoverMission (dm )) {
619+ return false ; // Don't remove recoverable missions
620+ }
621+ }
622+ return pending .remove (mission ) || finished .remove (mission );
623+ });
587624
588625 int fakeTotal = pending .size ();
589626 if (fakeTotal > 0 ) fakeTotal ++;
0 commit comments